SignalForge 0.0.2__tar.gz → 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. signalforge-1.0.0/PKG-INFO +157 -0
  2. {signalforge-0.0.2 → signalforge-1.0.0}/README.md +8 -0
  3. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge/__init__.py +1 -1
  4. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge/nonstationary_nongaussian.py +80 -17
  5. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge/single_chan_signal.py +214 -100
  6. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge/stationary_gaussian.py +26 -0
  7. signalforge-1.0.0/SignalForge/stationary_nongaussian.py +1438 -0
  8. signalforge-1.0.0/SignalForge/utils.py +1165 -0
  9. signalforge-1.0.0/SignalForge.egg-info/PKG-INFO +157 -0
  10. signalforge-1.0.0/pyproject.toml +39 -0
  11. signalforge-0.0.2/PKG-INFO +0 -23
  12. signalforge-0.0.2/SignalForge/stationary_nongaussian.py +0 -934
  13. signalforge-0.0.2/SignalForge/utils.py +0 -526
  14. signalforge-0.0.2/SignalForge.egg-info/PKG-INFO +0 -23
  15. signalforge-0.0.2/pyproject.toml +0 -3
  16. {signalforge-0.0.2 → signalforge-1.0.0}/LICENSE +0 -0
  17. {signalforge-0.0.2 → signalforge-1.0.0}/MANIFEST.in +0 -0
  18. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge.egg-info/SOURCES.txt +0 -0
  19. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge.egg-info/dependency_links.txt +0 -0
  20. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge.egg-info/requires.txt +0 -0
  21. {signalforge-0.0.2 → signalforge-1.0.0}/SignalForge.egg-info/top_level.txt +0 -0
  22. {signalforge-0.0.2 → signalforge-1.0.0}/requirements.txt +0 -0
  23. {signalforge-0.0.2 → signalforge-1.0.0}/setup.cfg +0 -0
  24. {signalforge-0.0.2 → signalforge-1.0.0}/setup.py +0 -0
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: SignalForge
3
+ Version: 1.0.0
4
+ Summary: A comprehensive Python package for generating and analyzing non-Gaussian and non-stationary signals.
5
+ Home-page: https://github.com/GiulioCurti/SignalForge
6
+ Author: Giulio Curti
7
+ Author-email: Giulio Curti <giulio.curti@dottorandi.unipg.it>
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/GiulioCurti/SignalForge
10
+ Project-URL: Documentation, https://signalforge.readthedocs.io/
11
+ Project-URL: Repository, https://github.com/GiulioCurti/SignalForge.git
12
+ Project-URL: Bug-Tracker, https://github.com/GiulioCurti/SignalForge/issues
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: numpy>=2.0
22
+ Requires-Dist: scipy
23
+ Requires-Dist: matplotlib>=3.10
24
+ Requires-Dist: tqdm
25
+ Requires-Dist: PyWavelets
26
+ Requires-Dist: pyNNST
27
+ Requires-Dist: statsmodels
28
+ Dynamic: author
29
+ Dynamic: home-page
30
+ Dynamic: license-file
31
+
32
+ [![SignalForge Testing](https://github.com/GiulioCurti/SignalForge/actions/workflows/python-app.yml/badge.svg)](https://github.com/GiulioCurti/SignalForge/actions/workflows/python-app.yml)
33
+ [![Documentation Status](https://app.readthedocs.org/projects/signalforge/badge/?version=latest)](https://signalforge.readthedocs.io/en/latest/)
34
+
35
+ SignalForge
36
+ -----------
37
+
38
+ SignalForge is an open-source Python package that provides a comprehensive set of tools for analyzing and generating non-Gaussian, non-stationary signals in engineering applications. While traditional signal processing methods often rely on assumptions of Gaussianity and stationarity, real-world signals—especially those found in mechanical systems—frequently deviate from these idealized models. SignalForge bridges this gap by offering advanced, yet user-friendly tools to simulate, inspect, and manipulate signals with complex statistical properties. Whether you're designing loads for testing, exploring time-varying behavior, or developing new algorithms, SignalForge enables you to work with signals that better reflect real operating conditions. Built with extensibility and clarity in mind, the package is suitable for researchers, practitioners, and students working across mechanical engineering, signal processing, and beyond.
39
+
40
+ See the [documentation](<https://signalforge.readthedocs.io/en/latest/>) for a complete overview of the implemented methods for analisys and signal generation.
41
+
42
+ Installing SignalForge
43
+ ------------------------------------------------------------
44
+ The package is published in PiPy. To install it:
45
+ ```bash
46
+ pip install signalforge
47
+ ```
48
+ or you can clone it from GitHub
49
+ ```bash
50
+ git clone https://github.com/GiulioCurti/SignalForge.git
51
+ ```
52
+ and locally install it from inside the folder SignalForge
53
+ ```bash
54
+ pip install -e .
55
+ ```
56
+
57
+ Example code on how to generate a Stationary Gaussian Signal
58
+ ------------------------------------------------------------
59
+
60
+ Stationary Gaussian signals can be easily generated via the specific class StationaryGaussian. Its usage is briefly shown in the following example code:
61
+
62
+ ```python
63
+ from SignalForge import StationaryGaussian
64
+
65
+ fpsd = [10,20] # Frequency vector [Hz]
66
+ psd = [1,1] # Power density vecrtor [(m/s^2)^2/Hz]
67
+ fs = 200 # Sampling frequency [Hz]
68
+ T = 200 # Time duration [s]
69
+ gauss_signal = StationaryGaussian(
70
+ fpsd=fpsd,
71
+ psd=psd,
72
+ fs=fs,
73
+ T = T,
74
+ name = 'Stationary Gaussian',
75
+ unit='$m/s^2$'
76
+ ) # StationaryGaussian class initialization
77
+ print(gauss_signal)
78
+ gauss_signal.plot() # Plotting Timehistory
79
+ gauss_signal.plot_psd() # Plotting Power spectral density
80
+ ```
81
+ Implemented non-linear transformartion methods to add non-gaussianity are the following:
82
+
83
+ - Hermite-Winterstein ('winter')
84
+ - Cubic polynomial ('cubic')
85
+ - Hyperbolic transform – Zheng (‘zheng’)
86
+ - Sarkani ('sarkani')
87
+ - Improved nonlinear transform ('zmnl')
88
+ - Steinwolf ('steinwolf')
89
+ - Smallwoood Poisson shots ('smallwood')
90
+ - Van Baren ('vanbaren')
91
+
92
+ Example code on how to generate a Stationary Non Gaussian Signal
93
+ ------------------------------------------------------------
94
+
95
+ Stationary non Gaussian signals can be easily generated via the specific class StationaryNonGaussian. Its usage is briefly shown in the following example code:
96
+
97
+ ```python
98
+ from SignalForge import StationaryNonGaussian
99
+
100
+ fpsd = [10,20] # Frequency vector [Hz]
101
+ psd = [1,1] # Power density vecrtor [(m/s^2)^2/Hz]
102
+ fs = 200 # Sampling frequency [Hz]
103
+ T = 200 # Time duration [s]
104
+ input_kurtosis = 6
105
+ nongauss_signal = StationaryNonGaussian(
106
+ fpsd = fpsd,
107
+ psd = psd,
108
+ T = T,
109
+ kurtosis=input_kurtosis,
110
+ fs = fs,
111
+ method='zmnl',
112
+ name = 'Stationary NonGaussian',
113
+ unit='$m/s^2$'
114
+ ) # StationaryNonGaussian class initalization
115
+ print(nongauss_signal)
116
+ nongauss_signal.plot() # Plotting Timehistory
117
+ nongauss_signal.plot_psd() # Plotting Power spectral density
118
+ nongauss_signal.plot_fft() # Plotting Fourier Transform
119
+ ```
120
+
121
+ Example code on how to generate a Non Stationary Non Gaussian Signal
122
+ ------------------------------------------------------------
123
+
124
+ Non stationary non Gaussian signals can be easily generated via the specific class NonStationaryGaussian. Its usage is briefly shown in the following example code:
125
+
126
+ ```python
127
+ from SignalForge import NonStationaryNonGaussian
128
+
129
+ fpsd = [10,20] # Frequency vector [Hz]
130
+ psd = [1,1] # Power density vecrtor [(m/s^2)^2/Hz]
131
+ fs = 200 # Sampling frequency [Hz]
132
+ T = 200 # Time duration [s]
133
+ params = {'input_kurtosis': 10}
134
+ nonstat_signal = NonStationaryNonGaussian(
135
+ fpsd = fpsd,
136
+ psd = psd,
137
+ T = T,
138
+ params = params,
139
+ fs = fs,
140
+ method='trapp_am',
141
+ name = 'NonStationary NonGaussian',
142
+ unit='$m/s^2$'
143
+ ) # NonStationaryNonGaussian class initalization
144
+ print(nonstat_signal)
145
+ nonstat_signal.plot() # Plotting Timehistory
146
+ nonstat_signal.plot_psd() # Plotting Timehistory
147
+ nonstat_signal.plot_sftf() # Plotting Short Time Fourier Transform
148
+ ```
149
+ Implemented transformartion methods to build non-gaussianity signals are the following:
150
+
151
+ - Beta amplitude modulation ('beta_am')
152
+ - Gaussian amplitude modulation ('trapp_am')
153
+ - Rayleigh amplitude modulation ('ray_am')
154
+ - Frequency modulation via STFT ('fm')
155
+
156
+
157
+
@@ -14,6 +14,14 @@ The package is published in PiPy. To install it:
14
14
  ```bash
15
15
  pip install signalforge
16
16
  ```
17
+ or you can clone it from GitHub
18
+ ```bash
19
+ git clone https://github.com/GiulioCurti/SignalForge.git
20
+ ```
21
+ and locally install it from inside the folder SignalForge
22
+ ```bash
23
+ pip install -e .
24
+ ```
17
25
 
18
26
  Example code on how to generate a Stationary Gaussian Signal
19
27
  ------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- __version__ = '0.0.2'
1
+ __version__ = '1.0.0'
2
2
  from .single_chan_signal import *
3
3
  from .stationary_gaussian import *
4
4
  from .stationary_nongaussian import *
@@ -1,7 +1,4 @@
1
- import numpy as np
2
- import scipy as sp
3
1
  import matplotlib.pyplot as plt
4
- from tqdm import tqdm
5
2
 
6
3
  from .utils import *
7
4
  from .single_chan_signal import SingleChanSignal
@@ -267,12 +264,48 @@ def get_trapp_amplitude_modulation(
267
264
  A. Trapp, M. J. Makua, e P. Wolfsteiner, «Fatigue assessment of amplitude-modulated non-stationary random vibration loading», Procedia Struct. Integr., vol. 17, pp. 379–386, 2019, doi: 10.1016/j.prostr.2019.08.050.
268
265
  """
269
266
  def get_trapp_carrier(p, delta_m, gaussian_carier):
270
- """Generate amplitude modulation carrier based on power-law transformation."""
267
+ """
268
+ Generate amplitude modulation carrier based on power-law transformation.
269
+
270
+ Parameters
271
+ ----------
272
+ p : float
273
+ Exponent for the power-law transformation.
274
+ delta_m : float
275
+ Offset for the amplitude modulation.
276
+ gaussian_carier : np.ndarray
277
+ The Gaussian carrier signal.
278
+
279
+ Returns
280
+ -------
281
+ np.ndarray
282
+ The transformed Rayleigh carrier signal.
283
+ """
271
284
  ray_carrier = np.abs(gaussian_carier)**p+delta_m
272
285
  return ray_carrier
273
286
 
274
287
  def trapp_am_opt_fun(params, gauss_carrier, input_kurtosis):
275
- """Optimization objective: match output signal kurtosis and reduce skew."""
288
+ """
289
+ Optimization objective function for Trapp amplitude modulation.
290
+
291
+ This function calculates the absolute difference between the transformed
292
+ signal's kurtosis and skewness and the target values.
293
+
294
+ Parameters
295
+ ----------
296
+ params : list
297
+ Parameters for the `get_trapp_carrier` function.
298
+ gauss_carrier : np.ndarray
299
+ The Gaussian carrier signal.
300
+ input_kurtosis : float
301
+ The target kurtosis.
302
+
303
+ Returns
304
+ -------
305
+ float
306
+ The absolute difference between the transformed signal's kurtosis and skewness
307
+ and the target values.
308
+ """
276
309
  carrier = get_trapp_carrier(*params, gaussian_carier=gauss_carrier)
277
310
  nonstat_sign = _add_am_carrier(gauss_signal, carrier)
278
311
  transformed_kurtosis = sp.stats.kurtosis(nonstat_sign) + 3
@@ -386,19 +419,49 @@ class NonStationaryNonGaussian(SingleChanSignal):
386
419
  PSD interpolation method: 'lin' or 'log'. Default is 'lin'.
387
420
  """
388
421
  def __init__(
389
- self,
390
- fpsd:np.ndarray,
391
- psd:np.ndarray,
392
- T:float,
422
+ self,
423
+ fpsd:np.ndarray,
424
+ psd:np.ndarray,
425
+ T:float,
393
426
  fs:float = None,
394
- dfpsd:float = 0.5,
395
- method:str = 'beta_am',
396
- params = None,
397
- name:str="",
398
- var:str='x',
399
- unit:str="$m/s^2$",
400
- seed:int=None,
401
- interp:str ='lin'):
427
+ dfpsd:float = 0.5,
428
+ method:str = 'beta_am',
429
+ params = None,
430
+ name:str="",
431
+ var:str='x',
432
+ unit:str="$m/s^2$",
433
+ seed:int=None,
434
+ interp:str ='lin'):
435
+ """
436
+ Initializes a NonStationaryNonGaussian signal generator.
437
+
438
+ Parameters
439
+ ----------
440
+ fpsd : np.ndarray
441
+ Frequency vector for the input PSD.
442
+ psd : np.ndarray
443
+ Power spectral density values.
444
+ T : float
445
+ Total duration of the signal [s].
446
+ fs : float, optional
447
+ Wanted sampling frequency. If None -> 2*fpsd[-1].
448
+ dfpsd : float, optional
449
+ Frequency resolution [Hz]. Default is 0.5.
450
+ method : str, optional
451
+ Modulation method: 'beta_am', 'ray_am', 'trapp_am', or 'fm'. Default is 'beta_am'.
452
+ params : dict, optional
453
+ Dictionary of parameters for the modulation method.
454
+ name : str, optional
455
+ Name of the signal.
456
+ var : str, optional
457
+ Variable symbol, e.g., 'x'.
458
+ unit : str, optional
459
+ Signal unit. Default is '$m/s^2$'.
460
+ seed : int, optional
461
+ Random seed for reproducibility.
462
+ interp : str, optional
463
+ PSD interpolation method: 'lin' or 'log'. Default is 'lin'.
464
+ """
402
465
 
403
466
  method = method.lower()
404
467
  interp = interp.lower()