anytimes 0.1.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 (49) hide show
  1. anytimes-0.1.0/ANYtimes_logo.png +0 -0
  2. anytimes-0.1.0/LICENSE +21 -0
  3. anytimes-0.1.0/MANIFEST.in +3 -0
  4. anytimes-0.1.0/PKG-INFO +105 -0
  5. anytimes-0.1.0/README.md +67 -0
  6. anytimes-0.1.0/anyqats/__init__.py +16 -0
  7. anytimes-0.1.0/anyqats/__main__.py +5 -0
  8. anytimes-0.1.0/anyqats/app/__init__.py +28 -0
  9. anytimes-0.1.0/anyqats/app/__main__.py +10 -0
  10. anytimes-0.1.0/anyqats/app/exceptions.py +47 -0
  11. anytimes-0.1.0/anyqats/app/funcs.py +245 -0
  12. anytimes-0.1.0/anyqats/app/gui.py +1592 -0
  13. anytimes-0.1.0/anyqats/app/logger.py +38 -0
  14. anytimes-0.1.0/anyqats/app/threading.py +67 -0
  15. anytimes-0.1.0/anyqats/app/widgets.py +48 -0
  16. anytimes-0.1.0/anyqats/cli.py +158 -0
  17. anytimes-0.1.0/anyqats/fatigue/__init__.py +5 -0
  18. anytimes-0.1.0/anyqats/fatigue/corrections.py +75 -0
  19. anytimes-0.1.0/anyqats/fatigue/rainflow.py +525 -0
  20. anytimes-0.1.0/anyqats/fatigue/sn.py +479 -0
  21. anytimes-0.1.0/anyqats/io/__init__.py +7 -0
  22. anytimes-0.1.0/anyqats/io/csv.py +52 -0
  23. anytimes-0.1.0/anyqats/io/direct_access.py +386 -0
  24. anytimes-0.1.0/anyqats/io/other.py +129 -0
  25. anytimes-0.1.0/anyqats/io/pickle_format.py +100 -0
  26. anytimes-0.1.0/anyqats/io/sima.py +358 -0
  27. anytimes-0.1.0/anyqats/io/sima_h5.py +219 -0
  28. anytimes-0.1.0/anyqats/io/sintef_mat.py +124 -0
  29. anytimes-0.1.0/anyqats/io/tdms.py +98 -0
  30. anytimes-0.1.0/anyqats/motions.py +154 -0
  31. anytimes-0.1.0/anyqats/signal.py +884 -0
  32. anytimes-0.1.0/anyqats/stats/__init__.py +5 -0
  33. anytimes-0.1.0/anyqats/stats/empirical.py +70 -0
  34. anytimes-0.1.0/anyqats/stats/gumbel.py +864 -0
  35. anytimes-0.1.0/anyqats/stats/gumbelmin.py +644 -0
  36. anytimes-0.1.0/anyqats/stats/weibull.py +1018 -0
  37. anytimes-0.1.0/anyqats/ts.py +1467 -0
  38. anytimes-0.1.0/anyqats/tsdb.py +1858 -0
  39. anytimes-0.1.0/anytimes/__init__.py +4 -0
  40. anytimes-0.1.0/anytimes/__main__.py +4 -0
  41. anytimes-0.1.0/anytimes/anytimes_gui.py +5840 -0
  42. anytimes-0.1.0/anytimes.egg-info/PKG-INFO +105 -0
  43. anytimes-0.1.0/anytimes.egg-info/SOURCES.txt +47 -0
  44. anytimes-0.1.0/anytimes.egg-info/dependency_links.txt +1 -0
  45. anytimes-0.1.0/anytimes.egg-info/entry_points.txt +2 -0
  46. anytimes-0.1.0/anytimes.egg-info/requires.txt +5 -0
  47. anytimes-0.1.0/anytimes.egg-info/top_level.txt +2 -0
  48. anytimes-0.1.0/pyproject.toml +29 -0
  49. anytimes-0.1.0/setup.cfg +4 -0
Binary file
anytimes-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Audun Arnesen Nyhus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ include README.md
2
+ include LICENSE
3
+ include ANYtimes_logo.png
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: anytimes
3
+ Version: 0.1.0
4
+ Summary: PySide6-based interface for exploring and editing time-series data.
5
+ Author: AnyTimes Developers
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Audun Arnesen Nyhus
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/example/anytimes
29
+ Requires-Python: >=3.8
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: numpy
33
+ Requires-Dist: pandas
34
+ Requires-Dist: scipy
35
+ Requires-Dist: PySide6
36
+ Requires-Dist: matplotlib
37
+ Dynamic: license-file
38
+
39
+ <p align="center">
40
+ <img src="ANYtimes_logo.png" alt="AnytimeSeries logo" width="200"/>
41
+ </p>
42
+
43
+ # ANYtimeSeries
44
+
45
+ ANYtimeSeries provides a QT-based interface for exploring and editing time-series data.
46
+
47
+ The application integrates with the bundled anyqats package and supports various file formats for loading and visualising time-series information.
48
+
49
+ Some of the features of ANYtimes
50
+ - loading of multiple files
51
+ - detection of commom variables files for effiecent work flow
52
+ - quick manipulation of time series using predefined operations
53
+ - complex manipulation of time series using equation input
54
+ - frequency filtering
55
+ - time sereis statistics
56
+ - many plotting options
57
+ - embdedded and in browser plotting
58
+ - Orcaflex .sim files compability
59
+ - extreme value statstics
60
+ - selection of plotting engine (plotly, bokeh or matplotlib)
61
+
62
+
63
+ <p align="center">
64
+ <img src="dark_mode.png" alt="AnytimeSeries dark mode" width="700"/>
65
+ </p>
66
+
67
+
68
+ <p align="center">
69
+ <img src="light_mode.png" alt="AnytimeSeries light mode" width="700"/>
70
+ </p>
71
+
72
+
73
+ <p align="center">
74
+ <img src="statistics_table.png" alt="AnytimeSeries statistics" width="700"/>
75
+ </p>
76
+
77
+ ## Installation
78
+
79
+ ```bash
80
+ pip install anytimes
81
+ ```
82
+
83
+ ## Requirements
84
+
85
+ - numpy
86
+ - pandas
87
+ - scipy
88
+ - anyqats
89
+ - PySide6
90
+ - matplotlib
91
+
92
+ ## Usage
93
+
94
+ After installation, import the GUI module in your Python project:
95
+
96
+ ```python
97
+ from anytimes import anytimes_gui
98
+ ```
99
+
100
+ The module exposes Qt widgets for building custom time-series exploration tools. You can also launch the GUI from the command line using the `anytimes` entry point.
101
+
102
+ ## License
103
+
104
+ Released under the MIT License. See [LICENSE](LICENSE) for details.
105
+
@@ -0,0 +1,67 @@
1
+ <p align="center">
2
+ <img src="ANYtimes_logo.png" alt="AnytimeSeries logo" width="200"/>
3
+ </p>
4
+
5
+ # ANYtimeSeries
6
+
7
+ ANYtimeSeries provides a QT-based interface for exploring and editing time-series data.
8
+
9
+ The application integrates with the bundled anyqats package and supports various file formats for loading and visualising time-series information.
10
+
11
+ Some of the features of ANYtimes
12
+ - loading of multiple files
13
+ - detection of commom variables files for effiecent work flow
14
+ - quick manipulation of time series using predefined operations
15
+ - complex manipulation of time series using equation input
16
+ - frequency filtering
17
+ - time sereis statistics
18
+ - many plotting options
19
+ - embdedded and in browser plotting
20
+ - Orcaflex .sim files compability
21
+ - extreme value statstics
22
+ - selection of plotting engine (plotly, bokeh or matplotlib)
23
+
24
+
25
+ <p align="center">
26
+ <img src="dark_mode.png" alt="AnytimeSeries dark mode" width="700"/>
27
+ </p>
28
+
29
+
30
+ <p align="center">
31
+ <img src="light_mode.png" alt="AnytimeSeries light mode" width="700"/>
32
+ </p>
33
+
34
+
35
+ <p align="center">
36
+ <img src="statistics_table.png" alt="AnytimeSeries statistics" width="700"/>
37
+ </p>
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install anytimes
43
+ ```
44
+
45
+ ## Requirements
46
+
47
+ - numpy
48
+ - pandas
49
+ - scipy
50
+ - anyqats
51
+ - PySide6
52
+ - matplotlib
53
+
54
+ ## Usage
55
+
56
+ After installation, import the GUI module in your Python project:
57
+
58
+ ```python
59
+ from anytimes import anytimes_gui
60
+ ```
61
+
62
+ The module exposes Qt widgets for building custom time-series exploration tools. You can also launch the GUI from the command line using the `anytimes` entry point.
63
+
64
+ ## License
65
+
66
+ Released under the MIT License. See [LICENSE](LICENSE) for details.
67
+
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Library for efficient processing and visualization of time series.
4
+ """
5
+ from .ts import TimeSeries
6
+ from .tsdb import TsDB
7
+
8
+ # version
9
+ try:
10
+ from ._version import __version__, __version_tuple__
11
+ except ImportError:
12
+ __version__ = "0.0.0"
13
+ __version_tuple__ = (0, 0, 0)
14
+
15
+ # summary
16
+ __summary__ = __doc__
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+ from . import cli
3
+
4
+ if __name__ == '__main__':
5
+ cli.main()
@@ -0,0 +1,28 @@
1
+ """Support for launching the AnyQATS GUI.
2
+
3
+ This module exposes a :func:`main` function that serves as an entry point
4
+ for the desktop application. It delegates to :func:`anyqats.cli.launch_app`
5
+ with default arguments, allowing the GUI to be started simply by executing
6
+ ``python -m anyqats.app``.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+
12
+ def main() -> None:
13
+ """Launch the graphical user interface.
14
+
15
+ The heavy lifting of setting up and starting the application lives in
16
+ :func:`anyqats.cli.launch_app`. Importing inside the function keeps import
17
+ time light and avoids circular dependencies during package initialisation.
18
+ """
19
+
20
+ from ..cli import launch_app
21
+
22
+ # Mirror the default behaviour of ``anyqats app`` which uses the current
23
+ # working directory unless the user specifies otherwise.
24
+ launch_app(home=False)
25
+
26
+
27
+ __all__ = ["main"]
28
+
@@ -0,0 +1,10 @@
1
+ """Module entry point for :mod:`anyqats.app`.
2
+
3
+ Executing ``python -m anyqats.app`` will invoke :func:`anyqats.app.main` and
4
+ start the graphical user interface.
5
+ """
6
+
7
+ from . import main
8
+
9
+ if __name__ == "__main__":
10
+ main()
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Module for custom exceptions and exception handlers
4
+ """
5
+ import os
6
+ import sys
7
+ import traceback
8
+ import webbrowser
9
+
10
+ from PySide6.QtWidgets import QMessageBox
11
+
12
+
13
+ def handle_exception(exc_type, exc_value, exc_traceback):
14
+ """
15
+ Handle all exceptions, log it on file, warn the user via a critical message box
16
+
17
+ Parameters
18
+ ----------
19
+ exc_type : type
20
+ type of exception e.g. ValueError
21
+ exc_value : str
22
+ exception string
23
+ exc_traceback : traceback
24
+ traceback for the exception
25
+
26
+ """
27
+ # retrieve traceback
28
+ filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
29
+ filename = os.path.basename(filename)
30
+ error = "%s: %s" % (exc_type.__name__, exc_value)
31
+
32
+ # display critical message box
33
+ msg = "<html>A critical error has occured.<br/> <b>%s</b><br/><br/>It occurred at <b>line %d</b> of file " \
34
+ "<b>%s</b>.<br/>Press Yes to see the full error report<br/></html>" % (error, line, filename)
35
+ message_box = QMessageBox().critical(None, "Error", msg.strip(), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
36
+
37
+ # pipe traceback to log file (env variable 'APPDATA' is assumed present on the computer)
38
+ log_file = os.path.join(os.getenv("APPDATA"), "QATS.launch.pyw.log")
39
+ with open(log_file,"w") as f:
40
+ f.write("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
41
+
42
+ # open log file in default editor if user pressed yes (trick using the webbrowser command)
43
+ if message_box == QMessageBox.Yes:
44
+ webbrowser.open(log_file)
45
+
46
+ # exit with code 1 (error)
47
+ sys.exit(1)
@@ -0,0 +1,245 @@
1
+ """
2
+ Module with functions for handling file operations and calculations. Made for multithreading.
3
+ """
4
+ import numpy as np
5
+
6
+ from ..fatigue.rainflow import rebin as rebin_cycles
7
+ from ..stats.gumbel import pwm as gumbel_pwm
8
+ from ..tsdb import TsDB
9
+
10
+
11
+ def calculate_psd(container, twin, fargs, nperseg, normalize):
12
+ """
13
+ Calculate power spectral density and return as numpy arrays
14
+
15
+ Parameters
16
+ ----------
17
+ container : dict
18
+ TimeSeries objects
19
+ twin : tuple
20
+ Time window. Time series are cropped to time window before estimating psd.
21
+ fargs : tuple
22
+ Filter arguments. Time series are filtered before estimating psd.
23
+ nperseg : int
24
+ Size of segments used for estimating PSD using Welch's method.
25
+ NOTE: the minimum of specified `nperseg` and signal length is used.
26
+ normalize : bool
27
+ Normalize power spectral density on maximum density.
28
+
29
+ Returns
30
+ -------
31
+ dict
32
+ Frequency versus power spectral density
33
+ """
34
+ container_out = dict()
35
+
36
+ for name, ts in container.items():
37
+ # NOTE: nperseg passed on as minimum of specified value and signal input length
38
+ # this is done in scipy anyway, which also issues a UserWArnings stating:
39
+ # "nperseg = {nperseg} is greater than input length = {input_length:d}, using nperseg = {input_length:d}"
40
+ t, _ = ts.get(twin=twin, resample=ts.dt)
41
+ nperseg_ = np.min((nperseg, t.size))
42
+ # calculate power spectral density
43
+ # (resampling to average time step for robustness, necessary for series with varying time step)
44
+ f, s = ts.psd(twin=twin, filterargs=fargs, resample=ts.dt, taperfrac=0.1, nperseg=nperseg_, normalize=normalize)
45
+ container_out[name] = tuple([f, s])
46
+
47
+ return container_out
48
+
49
+
50
+ def calculate_rfc(container, twin, fargs, nbins):
51
+ """
52
+ Count cycles using Rainflow counting method
53
+
54
+ Parameters
55
+ ----------
56
+ container : dict
57
+ TimeSeries objects
58
+ twin : tuple
59
+ Time window. Time series are cropped to time window before estimating psd.
60
+ fargs : tuple
61
+ Filter arguments. Time series are filtered before estimating psd.
62
+ nbins : int
63
+ Number of bins in cycle distribution.
64
+
65
+ Returns
66
+ -------
67
+ dict
68
+ Cycle magnitude versus count
69
+ """
70
+ container_out = dict()
71
+
72
+ for name, ts in container.items():
73
+ # rainflow counting
74
+ cycles = ts.rfc(twin=twin, filterargs=fargs)
75
+
76
+ # rebin
77
+ if nbins is not None:
78
+ cycles = rebin_cycles(cycles, binby='range', n=nbins)
79
+
80
+ # unpack pairs (tuples) in list
81
+ r, _, c = zip(*cycles)
82
+ container_out[name] = tuple([r, c])
83
+
84
+ return container_out
85
+
86
+
87
+ def calculate_trace(container, twin, fargs):
88
+ """
89
+ Calculate trace and peaks/troughs of filtered time series
90
+
91
+ Parameters
92
+ ----------
93
+ container : dict
94
+ TimeSeries objects
95
+ twin : tuple
96
+ Time window. Time series are cropped to time window before extracting maxima.
97
+ fargs : tuple
98
+ Filter arguments. Time series are filtered before extracting maxima.
99
+
100
+ Returns
101
+ -------
102
+ dict
103
+ Filtered and windowed time series and peaks/throughs
104
+ """
105
+ container_out = dict()
106
+
107
+ for name, ts in container.items():
108
+ t, x = ts.get(twin=twin, filterargs=fargs)
109
+ xmin, tmin = ts.minima(twin=twin, filterargs=fargs, rettime=True)
110
+ xmax, tmax = ts.maxima(twin=twin, filterargs=fargs, rettime=True)
111
+
112
+ container_out[name] = dict(t=t, x=x, tmin=tmin, xmin=xmin,
113
+ tmax=tmax, xmax=xmax)
114
+
115
+ return container_out
116
+
117
+
118
+ def calculate_stats(container, twin, fargs, minima=False):
119
+ """
120
+ Calculate time series statistics
121
+
122
+ Parameters
123
+ ----------
124
+ container : dict
125
+ TimeSeries objects
126
+ twin : tuple
127
+ Time window. Time series are cropped to time window before extracting maxima.
128
+ fargs : tuple
129
+ Filter arguments. Time series are filtered before extracting maxima.
130
+ minima : bool, optional
131
+ Fit to sample of minima instead of maxima. The sample is multiplied by -1 prior to parameter estimation.
132
+
133
+ Returns
134
+ -------
135
+ dict
136
+ Filtered and windowed time series and peaks/throughs
137
+ """
138
+ return {name: ts.stats(twin=twin, filterargs=fargs, statsdur=10800., quantiles=(0.37, 0.57, 0.9),
139
+ is_minima=minima, include_sample=True) for name, ts in container.items()}
140
+
141
+
142
+ def calculate_gumbel_fit(container, twin, fargs, minima=False):
143
+ """
144
+ Calculate time series extremes and fit Gumbel distribution
145
+
146
+ Parameters
147
+ ----------
148
+ container : dict
149
+ TimeSeries objects
150
+ twin : tuple
151
+ Time window. Time series are cropped to time window before extracting maxima.
152
+ fargs : tuple
153
+ Filter arguments. Time series are filtered before extracting maxima.
154
+ minima : bool, optional
155
+ Fit to sample of minima instead of maxima. The sample is multiplied by -1 prior to parameter estimation.
156
+
157
+ Returns
158
+ -------
159
+ dict
160
+ Sample and fitted gumbel distribution parameters
161
+ """
162
+ if len(container.keys()) < 2:
163
+ raise ValueError(f"Select more than 1 time series to fit Gumbel CDF to extremes sample.")
164
+
165
+ # create sample of extremes
166
+ sample = list()
167
+ for name, ts in container.items():
168
+ _, x = ts.get(twin=twin, filterargs=fargs)
169
+
170
+ if minima:
171
+ # sample minimum value
172
+ sample.append(np.min(x))
173
+ else:
174
+ # sample maximum value
175
+ sample.append(np.max(x))
176
+
177
+ # numpy array sorted ascending
178
+ sample = np.sort(np.array(sample))
179
+
180
+ # flip sample of minima to enable Gumbel fit
181
+ if minima:
182
+ sample *= -1
183
+
184
+ # estimate gumbel distribution parameters
185
+ loc, scale = gumbel_pwm(sample)
186
+ return dict(loc=loc, scale=scale, sample=sample, minima=minima)
187
+
188
+
189
+ def export_to_file(filename, db, names, twin, fargs):
190
+ """
191
+ Export selected time series to file
192
+
193
+ Parameters
194
+ ----------
195
+ filename : str
196
+ File name
197
+ db : TsDB
198
+ Time series data base
199
+ names : list
200
+ Name of time series to export
201
+ twin : tuple
202
+ Time window. Time series are cropped to time window before export.
203
+ fargs : tuple
204
+ Filter arguments. Time series are filtered before export
205
+ """
206
+ db.export(filename, names=names, exist_ok=True, basename=False, twin=twin, filterargs=fargs)
207
+
208
+
209
+ def import_from_file(files):
210
+ """
211
+ Import time series files
212
+
213
+ Parameters
214
+ ----------
215
+ files : list
216
+ File names
217
+
218
+ Returns
219
+ -------
220
+ TsDB
221
+ Time series data base
222
+ """
223
+ db = TsDB()
224
+ db.load(files, read=False)
225
+ return db
226
+
227
+
228
+ def read_timeseries(db, names):
229
+ """
230
+ Read time series from files
231
+
232
+ Parameters
233
+ ----------
234
+ db : TsDB
235
+ Time series data base
236
+ names : list
237
+ Name of time series to read
238
+
239
+ Returns
240
+ -------
241
+ dict
242
+ Container with TimeSeries objects
243
+ """
244
+ return db.getm(names=names, store=False)
245
+