diff --git a/.gitignore b/.gitignore index 8215b1a..65c73f7 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ __pycache__/__init__.cpython-39.pyc .ipynb_checkpoints/__init__-checkpoint.py tests/.ipynb_checkpoints/test_hstransform-checkpoint.py .DS_Store +.ipynb_checkpoints/setup-checkpoint.py diff --git a/.ipynb_checkpoints/setup-checkpoint.py b/.ipynb_checkpoints/setup-checkpoint.py deleted file mode 100644 index 1d9833d..0000000 --- a/.ipynb_checkpoints/setup-checkpoint.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -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' -) diff --git a/HSTransform.egg-info/PKG-INFO b/HSTransform.egg-info/PKG-INFO index 5b03c9c..2f7e7df 100644 --- a/HSTransform.egg-info/PKG-INFO +++ b/HSTransform.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: HSTransform -Version: 0.1.6 +Version: 0.1.1 Summary: A Package to Compute S-transform with Hyperbolic Window Home-page: https://github.com/nvlinhvn/HSTransform Author: Linh V Nguyen @@ -41,12 +41,18 @@ HS Transform requires the following Python packages: ## 3. How to Install -You can install HS Transform using pip: +After that, you can install HS Transform using pip: ``` pip install HSTransform ``` +You can also install all dependencies and package in 1 statement + +``` +pip install numpy scipy pandas matplotlib pytest HSTransform +``` + ## 4. Run tests After installation, you can test the package using the included test scripts: @@ -56,7 +62,18 @@ After installation, you can test the package using the included test scripts: Here’s an example of how to use HS Transform to analyze a signal with voltage disturbance and power system fault: +It's noted sometimes you need to include the installed HSTransform package location into sys + ```python +import sys +import os + +# Add the package directory to sys.path +package_path = os.path.abspath('/usr/local/Caskroom/miniconda/base/envs/YOUR_ENVIRONMENT/lib/python3.10/site-packages/') +if package_path not in sys.path: + sys.path.insert(0, package_path) + +import numpy as np from hstransform import HSTransform # Create input signal (for example: Voltage signal) @@ -80,6 +97,7 @@ S_transformed = hs.fit_transform(t, signal) ### 5.1 Power Quality Disturbance +Compare HS-transform vs. Morlet Wavelet Transform: ![Voltage Disturbance](https://raw.githubusercontent.com/nvlinhvn/HSTransform/main/img/power_quality_disturbance.png) The figure showed HS-transform is able to detect the transient disturbances like notch, spike. Meanwhile, those signals from Morlet Wavelet transform are not obviously recognized. diff --git a/README.md b/README.md index dd0aa2a..8e69e3b 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ package_path = os.path.abspath('/usr/local/Caskroom/miniconda/base/envs/YOUR_ENV if package_path not in sys.path: sys.path.insert(0, package_path) +import numpy as np from hstransform import HSTransform # Create input signal (for example: Voltage signal) @@ -82,6 +83,7 @@ S_transformed = hs.fit_transform(t, signal) ### 5.1 Power Quality Disturbance +Compare HS-transform vs. Morlet Wavelet Transform: ![Voltage Disturbance](https://raw.githubusercontent.com/nvlinhvn/HSTransform/main/img/power_quality_disturbance.png) The figure showed HS-transform is able to detect the transient disturbances like notch, spike. Meanwhile, those signals from Morlet Wavelet transform are not obviously recognized. diff --git a/dist/HSTransform-0.1.1-py3-none-any.whl b/dist/HSTransform-0.1.1-py3-none-any.whl new file mode 100644 index 0000000..622f165 Binary files /dev/null and b/dist/HSTransform-0.1.1-py3-none-any.whl differ diff --git a/dist/HSTransform-0.1.1.tar.gz b/dist/HSTransform-0.1.1.tar.gz new file mode 100644 index 0000000..993652b Binary files /dev/null and b/dist/HSTransform-0.1.1.tar.gz differ diff --git a/dist/HSTransform-0.1.6-py3-none-any.whl b/dist/HSTransform-0.1.6-py3-none-any.whl deleted file mode 100644 index 42801cf..0000000 Binary files a/dist/HSTransform-0.1.6-py3-none-any.whl and /dev/null differ diff --git a/dist/HSTransform-0.1.6.tar.gz b/dist/HSTransform-0.1.6.tar.gz deleted file mode 100644 index 46dc2b3..0000000 Binary files a/dist/HSTransform-0.1.6.tar.gz and /dev/null differ diff --git a/hstransform/.ipynb_checkpoints/__init__-checkpoint.py b/hstransform/.ipynb_checkpoints/__init__-checkpoint.py deleted file mode 100644 index d54e34e..0000000 --- a/hstransform/.ipynb_checkpoints/__init__-checkpoint.py +++ /dev/null @@ -1 +0,0 @@ -from .hstransform import HSTransform diff --git a/hstransform/.ipynb_checkpoints/hstransform-checkpoint.py b/hstransform/.ipynb_checkpoints/hstransform-checkpoint.py deleted file mode 100644 index 28d35dd..0000000 --- a/hstransform/.ipynb_checkpoints/hstransform-checkpoint.py +++ /dev/null @@ -1,133 +0,0 @@ -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 diff --git a/setup.py b/setup.py index 60edd5e..c35430e 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name='HSTransform', - version='0.1.6', + version='0.1.1', url='https://github.com/nvlinhvn/HSTransform', packages=find_packages(), license='MIT',