Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
fail-fast: false
matrix:
os: ["ubuntu-latest"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
# https://stackoverflow.com/questions/75549995/why-do-the-pyside6-qt-modules-cause-tox-to-fail-during-a-github-action
- name: Install missing libraries on GitHub agent
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ purposes. See deployment for notes on how to deploy the project on a live system

### Prerequisites

Install Python version 3.8 or later from either https://www.python.org or https://www.anaconda.com.
Install Python from https://www.python.org or https://www.anaconda.com.

Install Poetry with [the official installer](https://python-poetry.org/docs/#installing-with-the-official-installer).

Expand Down
6 changes: 2 additions & 4 deletions docs/source/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ Getting started
Prerequisites
*************

You need Python version 3.8 or later. Versions up to and including 3.11 are tested, version 3.12 is not tested on deployment
with Github Actions but successfully tested locally.

You can install Python from https://www.python.org or https://www.anaconda.com.
You need Python, which may be installed from for instance https://www.python.org or https://www.anaconda.com.
If not sure about which version to use, see supported python versions on https://pypi.org/project/qats/.

Installation
************
Expand Down
19 changes: 17 additions & 2 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,25 @@ Python version support

.. QATS currently supports Python version 3.8 and later. Note that version 3.12 is not properly tested but should work.

QATS currently supports Python version 3.8+.
.. QATS currently supports Python version 3.8+.

QATS aims to support Python versions in accordance with the official `Status of Python versions <https://devguide.python.org/versions>`_ (that is, versions with status **security** and **bugfix**).

The Python versions suported by the latest version of QATS are:

.. image:: https://img.shields.io/pypi/pyversions/qats
:target: https://pypi.org/project/qats/

.. note::
Python version <=3.11 is recommended, as version 3.12 is not yet formally tested.

The Python version support for a specific version of QATS is best seen from the metadata on `PyPi/qats <https://pypi.org/project/qats/>`_.


.. .. image:: https://img.shields.io/pypi/pyversions/qats
.. :target: https://pypi.org/project/qats/

.. .. note::
.. Python version <=3.11 is recommended, as version 3.12 is not yet formally tested.



Expand Down
39 changes: 32 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,26 @@ name = "pypi-public"
url = "https://pypi.org/simple/"

[tool.poetry.dependencies]
python = ">=3.8.1,<3.13"
h5py = ">=3.5.0"
python = ">=3.8.1,<3.14"
# h5py = ">=3.5.0"
h5py = [
{version = ">=3.5.0", python = "<3.13"},
{version = ">=3.12.1", python = ">=3.13"}
]
contourpy = [ # dependency of h5py, automatic version fails when installing for python 3.13
{version = ">=1.0.1", python = "<3.13"},
{version = ">=1.3.1", python = ">=3.13"},
]
pymatreader = ">=0.0.24"
matplotlib = ">=3.3.3"
matplotlib = [
{version = ">=3.3.3", python = "<3.13"},
{version = ">=3.9.1", python = ">=3.13"}
]
nptdms = ">=1.1.0"
numpy = [
{version = ">=1.21.6", python = "<3.12"},
{version = ">=1.26.0", python = ">=3.12"}
{version = ">=1.26.0", python = ">=3.12,<3.13"},
{version = ">=2.1.0", python = ">=3.13"}
]
openpyxl = ">=3.0.5"
pandas = [
Expand All @@ -50,10 +62,23 @@ pandas = [
qtpy = ">=1.9.0"
scipy = [
{version = ">=1.9.0", python = "<3.12"},
{version = ">=1.11.1", python = ">=3.12"}
{version = ">=1.11.1", python = ">=3.12,<3.13"},
{version = ">=1.14.1", python = ">=3.13"}
]
pywin32 = [ # MUST check the appropriate constraint
{version = "^306", markers = "platform_system == 'Windows'", python = "<3.13"},
{version = "^308", markers = "platform_system == 'Windows'", python = ">=3.13"},
]
pyside6 = [
# temporary fix: avoid pyside6 version 6.8.1.1, which misses it companion shiboken6 6.8.1.1 on pypi
# see issue 134, https://github.com/dnvgl/qats/issues/134
# may allow for version >=6.8.1 again when this has been fixed on pyside/shiboken side,
# e.g.:
# {version = "">=6.6.0,<6.9", python = "<3.13"},
# {version = "~=6.8.1", python = ">3.13"}
{version = ">=6.6.0,<=6.8.1", python = "<3.13"},
{version = "6.8.1", python = ">=3.13"}
]
pywin32 = {version = "^306", markers = "platform_system == 'Windows'"} # MUST check the appropriate constraint
pyside6 = "^6.6.0"
importlib-resources = "*"

[tool.poetry.group.dev.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion qats/fatigue/rainflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def count_cycles(series, endpoints=False):

See Also
--------
reversals, cycles
reversals, cycles, qats.signal.find_reversals

"""
full, half = cycles(series, endpoints=endpoints)
Expand Down
26 changes: 16 additions & 10 deletions qats/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,8 @@ def find_reversals(x) -> Tuple[np.ndarray, np.ndarray]:
"""
Return reversals (signal turning points).

.. versionadded :: 5.2.0

Parameters
----------
x : array
Expand All @@ -642,44 +644,48 @@ def find_reversals(x) -> Tuple[np.ndarray, np.ndarray]:
array
Indices of reversals.


Notes
-----
.. versionadded :: 5.2.0


This function provides quick identification of signal reversals (turning points), as an alternative
to `qats.fatigue.rainflow.reversals()` which is slower for large signal arrays. Note that if the
to ``qats.fatigue.rainflow.reversals()`` which is slower for large signal arrays. Note that if the
signal includes oscillations with high frequency compared to the frequency oscillations (e.g., due
to noise in the signal causing), the present function may in some cases include some very local
turning points that are not identified by `qats.fatigue.rainflow.reversals()`. However, when the
turning points obtained from `find_reversals()` are passed through `reversals()`
(with `endpoints=True`), the resulting array will normally be the same as if the signal itself was
passed through `reversals()`.
turning points that are not identified by ``qats.fatigue.rainflow.reversals()``. However, when the
turning points obtained from ``find_reversals()`` are passed through ``reversals()``
(with ``endpoints=True``), the resulting array will normally be the same as if the signal itself was
passed through ``reversals()``.

Specifically, the following two code lines will **not** necessarily produce identical arrays:

>>> from qats.fatigue.rainflow import reversals
>>> rev1 = np.array(list(reversals(x)))
>>> rev2, _ = find_reversals(x)

... but the following code lines will normally produce `rev3` identical to `rev1` above:
... but the following code lines will normally produce ``rev3`` identical to ``rev1`` above:

>>> rev3 = np.array(list(reversals(rev2, endpoints=True)))

Examples
--------
Extract reversals (turning points) from the time series signal `x`:
Extract reversals (turning points) from the time series signal ``x``:

>>> rev, _ = find_reversals(x)

Extract reversals and corresponding indices:

>>> rev, indices = find_reversals(x)

Use `find_reversals()` to speed up cycle counting:
Use ``find_reversals()`` to speed up cycle counting:

>>> from qats.fatigue.rainflow import count_cycles
>>> rev, _ = find_reversals(x)
>>> cycles = count_cycles(rev, endpoints=True)

For large arrays, the latter example is practically equivalent to (but faster than)
the following code:

>>> cycles = count_cycles(x)
"""
# local maxima and minima (all peaks, both positive and negative)
Expand Down
12 changes: 4 additions & 8 deletions qats/stats/gumbel.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,24 +825,20 @@ def mk(z, k):

Notes
-----
The probability weighted moment Mljk is defined by Greenwood and others (1979)

.. math::
The probability weighted moment Mljk is defined by Greenwood and others (1979)::

M_{l,j,k} = E[X^l F^j (1-F)^k]

, where X(F) is the inverse form of the distribution and F is the cumulative distribution function.
where X(F) is the inverse form of the distribution and F is the cumulative distribution function.
When j=k=0 and l is a non-negative integer then M_{l,0,0} represents the conventional moment of order l about
the origin.

PWMs can be applied either when the small observations are more important than the large observations (k=0), as in
strength properties of materials, or when the large observations should have more influence than the smaller
observations (k=0) as with three diameter distribution modelling. Here we have chose the former and derived
unbiased estimators for moments M_{1,0,k} (j=0), see eq. 16 in [6].

.. math::
unbiased estimators for moments M_{1,0,k} (j=0), see eq. 16 in [6]::

M_{1,0,k} = \frac{1}{n}\sum_{i=1}^{n}{X_{(i)}\frac{\binom{n-i}{k}}{\binom{n-1}{k}}}
M_{1,0,k} = \\frac{1}{n}\\sum_{i=1}^{n}{X_{(i)}\\frac{\\binom{n-i}{k}}{\\binom{n-1}{k}}}

"""
n = float(z.size)
Expand Down
4 changes: 2 additions & 2 deletions qats/stats/weibull.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ def mlj(sample, l, j):

M_{l,j,k} = E[X^l * F^j * (1-F)^k]

, where `X(F)` is the inverse form of the distribution and `F` is the cumulative distribution function.
where `X(F)` is the inverse form of the distribution and `F` is the cumulative distribution function.
When `j=k=0` and `l` is a non-negative integer, then `M_{l,0,0}` represents the conventional moment of order `l`
about the origin.

Expand All @@ -799,7 +799,7 @@ def mlj(sample, l, j):
# todo: include pseudo-code (or Sphinx-friendly LaTex code) for M_{l,j,0} as included below
'''
.. math:: M_{l,j,k} = E[X^l F^j (1-F)^k]
.. math:: M_{l,j,0} = \frac{1}{n}\sum_{i=j+1}^{n}{X_{(i)}^l\frac{\binom{i-1}{j}}{\binom{n-1}{j}}}
.. math:: M_{l,j,0} = \\frac{1}{n}\\sum_{i=j+1}^{n}{X_{(i)}^l\\frac{\\binom{i-1}{j}}{\\binom{n-1}{j}}}
'''
n = float(sample.size)
xi = np.sort(sample)[j:] # (j+1)th subsample of sorted sample
Expand Down