Skip to content

Commit

Permalink
Fixed setup and package
Browse files Browse the repository at this point in the history
- Build hstransform module
- Fix import error
  • Loading branch information
nvlinhvn committed May 19, 2024
1 parent 08d132d commit a0f5d5c
Show file tree
Hide file tree
Showing 14 changed files with 318 additions and 2 deletions.
38 changes: 38 additions & 0 deletions .ipynb_checkpoints/setup-checkpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
This is the setup module for the HSTransform package. (Beta test)
S-transform with Hyperbolic Window
Combines the best properties of the Short-time Fourier Transform
and the Wavelet Transform.
"""

from setuptools import setup, find_packages

with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()

setup(
name='HSTransform',
version='0.1.5',
url='https://github.com/nvlinhvn/HSTransform',
packages=find_packages(),
license='MIT',
author='Linh V Nguyen',
author_email='linhvietnguyen.ee@gmail.com',
description='A Package to Compute S-transform with Hyperbolic Window',
python_requires='>=3.10',
long_description=long_description,
long_description_content_type="text/markdown",
install_requires=[
'numpy>=1.21.2',
'scipy>=1.7.1',
'pandas>=1.3.3',
'pytest>=6.2.5'
],
classifiers=[
'Development Status :: 4 - Beta',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.10',
],
test_suite='tests'
)
4 changes: 4 additions & 0 deletions HSTransform.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.21.2
Requires-Dist: scipy>=1.7.1
Requires-Dist: pandas>=1.3.3
Requires-Dist: pytest>=6.2.5

# Hyperbolic S-Transform

Expand Down
2 changes: 2 additions & 0 deletions HSTransform.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ HSTransform.egg-info/SOURCES.txt
HSTransform.egg-info/dependency_links.txt
HSTransform.egg-info/requires.txt
HSTransform.egg-info/top_level.txt
hstransform/__init__.py
hstransform/hstransform.py
tests/__init__.py
tests/test_hstransform.py
1 change: 0 additions & 1 deletion HSTransform.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
numpy>=1.21.2
scipy>=1.7.1
pandas>=1.3.3
matplotlib>=3.4.3
pytest>=6.2.5
1 change: 1 addition & 0 deletions HSTransform.egg-info/top_level.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
hstransform
tests
1 change: 0 additions & 1 deletion __init__.py

This file was deleted.

1 change: 1 addition & 0 deletions build/lib/hstransform/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .hstransform import HSTransform
135 changes: 135 additions & 0 deletions build/lib/hstransform/hstransform.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import dataclasses
from typing import Union

import numpy as np
from scipy.fft import fft, ifft
import pandas as pd


@dataclasses.dataclass
class HSTransform:
"""
A class used to represent the S-transform with a hyperbolic Gaussian window.
...
Attributes
----------
forwardtaper : float
forward taper value
backwardtaper : float
backward taper value
curvature : float
curvature value
"""

forwardtaper: float = 0.2
backwardtaper: float = 0.1
curvature: float = 312.5

def _input_validation(self, input_signal):
"""
Validates the input signal.
Parameters
----------
input_signal : np.ndarray, pd.Series, or list
Raises
------
TypeError: If input_signal is not a numpy array, pandas Series, or list.
ValueError: If input_signal contains non-numerical values.
"""
valid_types = (np.ndarray, pd.Series, list)
if not isinstance(input_signal, valid_types):
raise TypeError(f"input_signal must be one of the following types: {valid_types}, not {type(input_signal)}.")

input_array = np.array(input_signal)
if np.isnan(input_array).any():
raise ValueError("input_signal contains null values.")

if not np.issubdtype(input_array.dtype, np.number):
raise ValueError("input_signal should only contain numerical values.")

def _compute_hyperbolic_gaussian(self, l: int, n: int, time: np.ndarray) -> np.ndarray:
"""
Computes the hyperbolic Gaussian window.
Parameters
----------
l : int
length of the signal
n : int
frequency point
time : np.ndarray
time values of the signal
Returns
-------
g : np.ndarray
hyperbolic Gaussian window
"""
vectorf = np.arange(0, l)
vectorf1 = vectorf**2
lambdaf = self.forwardtaper
lambdab = self.backwardtaper
lambda_val = self.curvature
x = (lambdaf + lambdab) * time / (2 * lambdaf * lambdab) + (lambdaf - lambdab) * np.sqrt(time**2 + lambda_val) / (2 * lambdaf * lambdab)
x = np.tile(x, (1, 2)).T
vectorf2 = -vectorf1 * x**2 / (2 * n**2)
g = 2 * np.abs(vectorf) * np.exp(vectorf2) / ((lambdaf + lambdab) * np.sqrt(2 * np.pi))
return np.sum(g)

def fit_transform(self,
time_values: Union[pd.Series, np.ndarray, list],
input_signal: Union[pd.Series, np.ndarray, list],
minf: int = 0,
fsamplingrate: int = 1) -> np.ndarray:
"""
Computes the S-transform of the input signal.
Parameters
----------
time_values : np.ndarray
time values of the signal
input_signal : np.ndarray
input signal
minf : int
minimum frequency point
fsamplingrate : int
frequency sampling rate
Returns
-------
S : np.ndarray
S-transform of the input signal
"""
# Validate the input
self._input_validation(input_signal)

# Convert to numpy arrays if they are not array types
if not isinstance(time_values, np.ndarray):
time_values = np.array(time_values)
if not isinstance(input_signal, np.ndarray):
input_signal = np.array(input_signal)

n = len(input_signal)
# Make sure the max frequency to be optimized (Cover the 6th, 12th, or 18th harmonic respectively)
maxf = min(900, n // 2)

# Compute the fft of input
h = fft(input_signal)
h = np.concatenate((h, h))

# S output
s = np.zeros(((maxf - minf + 1) // fsamplingrate, n), dtype='complex')
s[0, :] = np.mean(input_signal) * (1 & np.arange(1, n + 1))

# Increment the frequency point
for k in range(fsamplingrate, maxf - minf + 1, fsamplingrate):
w_hy = self._compute_hyperbolic_gaussian(n, minf + k, time_values)
s[k // fsamplingrate, :] = ifft(h[minf + k + 1:minf + k + n+1] * w_hy)

return s


Binary file removed dist/HSTransform-0.1.5-py3-none-any.whl
Binary file not shown.
Binary file removed dist/HSTransform-0.1.5.tar.gz
Binary file not shown.
1 change: 1 addition & 0 deletions hstransform/.ipynb_checkpoints/__init__-checkpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .hstransform import HSTransform
File renamed without changes.
1 change: 1 addition & 0 deletions hstransform/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .hstransform import HSTransform
135 changes: 135 additions & 0 deletions hstransform/hstransform.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import dataclasses
from typing import Union

import numpy as np
from scipy.fft import fft, ifft
import pandas as pd


@dataclasses.dataclass
class HSTransform:
"""
A class used to represent the S-transform with a hyperbolic Gaussian window.
...
Attributes
----------
forwardtaper : float
forward taper value
backwardtaper : float
backward taper value
curvature : float
curvature value
"""

forwardtaper: float = 0.2
backwardtaper: float = 0.1
curvature: float = 312.5

def _input_validation(self, input_signal):
"""
Validates the input signal.
Parameters
----------
input_signal : np.ndarray, pd.Series, or list
Raises
------
TypeError: If input_signal is not a numpy array, pandas Series, or list.
ValueError: If input_signal contains non-numerical values.
"""
valid_types = (np.ndarray, pd.Series, list)
if not isinstance(input_signal, valid_types):
raise TypeError(f"input_signal must be one of the following types: {valid_types}, not {type(input_signal)}.")

input_array = np.array(input_signal)
if np.isnan(input_array).any():
raise ValueError("input_signal contains null values.")

if not np.issubdtype(input_array.dtype, np.number):
raise ValueError("input_signal should only contain numerical values.")

def _compute_hyperbolic_gaussian(self, l: int, n: int, time: np.ndarray) -> np.ndarray:
"""
Computes the hyperbolic Gaussian window.
Parameters
----------
l : int
length of the signal
n : int
frequency point
time : np.ndarray
time values of the signal
Returns
-------
g : np.ndarray
hyperbolic Gaussian window
"""
vectorf = np.arange(0, l)
vectorf1 = vectorf**2
lambdaf = self.forwardtaper
lambdab = self.backwardtaper
lambda_val = self.curvature
x = (lambdaf + lambdab) * time / (2 * lambdaf * lambdab) + (lambdaf - lambdab) * np.sqrt(time**2 + lambda_val) / (2 * lambdaf * lambdab)
x = np.tile(x, (1, 2)).T
vectorf2 = -vectorf1 * x**2 / (2 * n**2)
g = 2 * np.abs(vectorf) * np.exp(vectorf2) / ((lambdaf + lambdab) * np.sqrt(2 * np.pi))
return np.sum(g)

def fit_transform(self,
time_values: Union[pd.Series, np.ndarray, list],
input_signal: Union[pd.Series, np.ndarray, list],
minf: int = 0,
fsamplingrate: int = 1) -> np.ndarray:
"""
Computes the S-transform of the input signal.
Parameters
----------
time_values : np.ndarray
time values of the signal
input_signal : np.ndarray
input signal
minf : int
minimum frequency point
fsamplingrate : int
frequency sampling rate
Returns
-------
S : np.ndarray
S-transform of the input signal
"""
# Validate the input
self._input_validation(input_signal)

# Convert to numpy arrays if they are not array types
if not isinstance(time_values, np.ndarray):
time_values = np.array(time_values)
if not isinstance(input_signal, np.ndarray):
input_signal = np.array(input_signal)

n = len(input_signal)
# Make sure the max frequency to be optimized (Cover the 6th, 12th, or 18th harmonic respectively)
maxf = min(900, n // 2)

# Compute the fft of input
h = fft(input_signal)
h = np.concatenate((h, h))

# S output
s = np.zeros(((maxf - minf + 1) // fsamplingrate, n), dtype='complex')
s[0, :] = np.mean(input_signal) * (1 & np.arange(1, n + 1))

# Increment the frequency point
for k in range(fsamplingrate, maxf - minf + 1, fsamplingrate):
w_hy = self._compute_hyperbolic_gaussian(n, minf + k, time_values)
s[k // fsamplingrate, :] = ifft(h[minf + k + 1:minf + k + n+1] * w_hy)

return s


0 comments on commit a0f5d5c

Please sign in to comment.