From 48e66877fad33cafba7f0dbdd4fee152c82c7cdf Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 20:46:19 +0100 Subject: [PATCH 01/21] Bump Numpy version and fix complex type --- .github/workflows/tests.yaml | 8 ++++++-- .gitignore | 1 + requirements.txt | 20 ++++++++++---------- requirements/docs.txt | 30 +++++++++++++++--------------- requirements/extra.txt | 19 ++++++------------- traja/tests/test_trajectory.py | 2 +- traja/trajectory.py | 2 +- 7 files changed, 40 insertions(+), 42 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 046c4ec3..9e15a6c0 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,15 +14,18 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "windows-latest"] + python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] steps: - uses: actions/checkout@v2 - - uses: conda-incubator/setup-miniconda@v2 + - name: Set up Miniconda ${{ matrix.python-version }} + uses: conda-incubator/setup-miniconda@v2 with: activate-environment: test channels: conda-forge,defaults environment-file: environment.yml - python-version: 3.8 + python-version: ${{ matrix.python-version }} auto-activate-base: false + cache-dependencies: true - shell: bash -l {0} run: | conda info @@ -44,6 +47,7 @@ jobs: conda install pytest py.test . --cov-report=xml --cov=traja -vvv - name: Upload coverage to Codecov + if: ${{ matrix.python-version }} == '3.8' uses: codecov/codecov-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index c3f65827..679af2c0 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,4 @@ docs/source/reference # Model parameter files *.pt +.python-version diff --git a/requirements.txt b/requirements.txt index 263feb79..7a3de661 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ pandas>=1.2.0 -numpy==1.18.5 -matplotlib -shapely -scipy>=1.4.1 -fastdtw -networkx -seaborn -torch -statsmodels -scikit-learn \ No newline at end of file +numpy>=1.22.0 +matplotlib>=3.3.3 +shapely>=1.7.1 +scipy>=1.2.1 +fastdtw>=0.3.0 +networkx>=2.0 +seaborn>=0.11.0 +torch>=1.7.0 +statsmodels>=0.12.0 +scikit-learn>=0.24.0 \ No newline at end of file diff --git a/requirements/docs.txt b/requirements/docs.txt index 7a8b4307..2a2c5934 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,17 +1,17 @@ pandas>=1.2.0 numpy==1.18.5 -matplotlib -shapely -scipy -scikit-learn -sphinx -sphinx-gallery -sphinx_rtd_theme -fastdtw -networkx -seaborn -torch -pytest -pytest-cov -codecov -ipython +matplotlib>=3.3.3 +shapely>=1.7.1 +scipy>=1.2.1 +scikit-learn>=0.24.0 +sphinx>=3.4.3 +sphinx-gallery>=0.9.0 +sphinx_rtd_theme>=0.5.1 +fastdtw>=0.3.0 +networkx>=2.0 +seaborn>=0.11.0 +torch>=1.7.0 +pytest>=6.2.2 +pytest-cov>=2.11.1 +codecov>=2.1.11 +ipython>=7.20.0 diff --git a/requirements/extra.txt b/requirements/extra.txt index 9193415a..9c494ac1 100644 --- a/requirements/extra.txt +++ b/requirements/extra.txt @@ -1,16 +1,9 @@ # extended list of package dependencies to reach full functionality -pytest -h5py -ipython -pre-commit -shapely -scipy>=1.4.1 -scikit-learn -fastdtw -networkx -seaborn -torch -h5py -numba>=0.50.0 +pytest>=6.2.2 +h5py>=2.10.0 +ipython>=7.19.0 +pre-commit>=2.9.3 +h5py>=2.10.0 +numba>=0.50.1 pyDOE2>=1.3.0 \ No newline at end of file diff --git a/traja/tests/test_trajectory.py b/traja/tests/test_trajectory.py index 864889bd..b64800df 100644 --- a/traja/tests/test_trajectory.py +++ b/traja/tests/test_trajectory.py @@ -1,7 +1,7 @@ import numpy as np import numpy.testing as npt import pytest -from pandas.util.testing import assert_series_equal +from pandas.testing import assert_series_equal import traja diff --git a/traja/trajectory.py b/traja/trajectory.py index a28c2305..51f672e1 100644 --- a/traja/trajectory.py +++ b/traja/trajectory.py @@ -668,7 +668,7 @@ def generate( if random: # Accumulate angular errors - coords = np.zeros(n, dtype=np.complex) + coords = np.zeros(n, dtype=complex) angle = 0 for i in range(n - 1): angle += angular_errors[i] From cca542754e7bf974423b84d58d9aebdea436fb21 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 20:50:21 +0100 Subject: [PATCH 02/21] Remove incorrect github actions option --- .github/workflows/tests.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 9e15a6c0..51a640a5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -25,7 +25,6 @@ jobs: environment-file: environment.yml python-version: ${{ matrix.python-version }} auto-activate-base: false - cache-dependencies: true - shell: bash -l {0} run: | conda info From c8de31ba3376d527127b738fd390938bad318295 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 20:53:48 +0100 Subject: [PATCH 03/21] Upgrade PyTest dependency --- requirements/extra.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/extra.txt b/requirements/extra.txt index 9c494ac1..01c73e9a 100644 --- a/requirements/extra.txt +++ b/requirements/extra.txt @@ -1,6 +1,6 @@ # extended list of package dependencies to reach full functionality -pytest>=6.2.2 +pytest>=8.1.1 h5py>=2.10.0 ipython>=7.19.0 pre-commit>=2.9.3 From 8b6f9516352fd2ab99b465a1fbee0147a0a1d736 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 20:57:31 +0100 Subject: [PATCH 04/21] Remove extraneous requirements --- requirements.txt | 18 +++++++++--------- requirements/docs.txt | 2 +- requirements/extra.txt | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7a3de661..7b597ce0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ pandas>=1.2.0 numpy>=1.22.0 -matplotlib>=3.3.3 -shapely>=1.7.1 -scipy>=1.2.1 -fastdtw>=0.3.0 -networkx>=2.0 -seaborn>=0.11.0 -torch>=1.7.0 -statsmodels>=0.12.0 -scikit-learn>=0.24.0 \ No newline at end of file +matplotlib +shapely +scipy>=1.4.1 +fastdtw +networkx +seaborn +torch +statsmodels +scikit-learn \ No newline at end of file diff --git a/requirements/docs.txt b/requirements/docs.txt index 2a2c5934..8311cdec 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -11,7 +11,7 @@ fastdtw>=0.3.0 networkx>=2.0 seaborn>=0.11.0 torch>=1.7.0 -pytest>=6.2.2 +pytest>=8.1.1 pytest-cov>=2.11.1 codecov>=2.1.11 ipython>=7.20.0 diff --git a/requirements/extra.txt b/requirements/extra.txt index 01c73e9a..db0a9eb2 100644 --- a/requirements/extra.txt +++ b/requirements/extra.txt @@ -1,9 +1,9 @@ # extended list of package dependencies to reach full functionality pytest>=8.1.1 -h5py>=2.10.0 -ipython>=7.19.0 -pre-commit>=2.9.3 -h5py>=2.10.0 +h5py +ipython +pre-commit +h5py numba>=0.50.1 pyDOE2>=1.3.0 \ No newline at end of file From 5360ab6a3b1dd91af79c469f1ec6549f703513f5 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 21:01:52 +0100 Subject: [PATCH 05/21] Remove pytest version --- requirements/extra.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/extra.txt b/requirements/extra.txt index db0a9eb2..1c22641e 100644 --- a/requirements/extra.txt +++ b/requirements/extra.txt @@ -1,6 +1,6 @@ # extended list of package dependencies to reach full functionality -pytest>=8.1.1 +pytest h5py ipython pre-commit From 84ff54aad2cd9748666edccb2ea9cd794c3b56f8 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 21:05:30 +0100 Subject: [PATCH 06/21] Remove conflicting python versions --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 51a640a5..174240c3 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "windows-latest"] - python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] + python-version: [ "3.8", "3.9" ] steps: - uses: actions/checkout@v2 - name: Set up Miniconda ${{ matrix.python-version }} From b0d10d952340faff87c2af7fcdfa0e527a1abbef Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Fri, 5 Apr 2024 21:11:27 +0100 Subject: [PATCH 07/21] Bump docs numpy --- requirements/docs.txt | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/requirements/docs.txt b/requirements/docs.txt index 8311cdec..c2dfee6c 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,17 +1,17 @@ pandas>=1.2.0 -numpy==1.18.5 -matplotlib>=3.3.3 -shapely>=1.7.1 -scipy>=1.2.1 -scikit-learn>=0.24.0 -sphinx>=3.4.3 -sphinx-gallery>=0.9.0 -sphinx_rtd_theme>=0.5.1 -fastdtw>=0.3.0 -networkx>=2.0 -seaborn>=0.11.0 -torch>=1.7.0 -pytest>=8.1.1 -pytest-cov>=2.11.1 -codecov>=2.1.11 -ipython>=7.20.0 +numpy>=1.22.0 +matplotlib +shapely +scipy +scikit-learn +sphinx +sphinx-gallery +sphinx_rtd_theme +fastdtw +networkx +seaborn +torch +pytest +pytest-cov +codecov +ipython From e3c91900888e576ef241c1f002a9544a4f5c85d9 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 14:38:52 +0100 Subject: [PATCH 08/21] Replace depreated pandas function with local alternative --- traja/core.py | 5 +++++ traja/plotting.py | 3 +-- traja/trajectory.py | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 traja/core.py diff --git a/traja/core.py b/traja/core.py new file mode 100644 index 00000000..ec274fe0 --- /dev/null +++ b/traja/core.py @@ -0,0 +1,5 @@ +import pandas as pd + +# Check whether pandas series is datetime or timedelta +def is_datetime_or_timedelta_dtype(series: pd.Series) -> bool: + return pd.api.types.is_datetime64_dtype(series) or pd.api.types.is_timedelta64_dtype(series) \ No newline at end of file diff --git a/traja/plotting.py b/traja/plotting.py index 391d75bc..bb9fc6e0 100644 --- a/traja/plotting.py +++ b/traja/plotting.py @@ -14,15 +14,14 @@ from matplotlib.axes import Axes from matplotlib.collections import PathCollection from matplotlib.figure import Figure -from mpl_toolkits.mplot3d import Axes3D from pandas.core.dtypes.common import ( - is_datetime_or_timedelta_dtype, is_datetime64_any_dtype, is_timedelta64_dtype, ) import traja from traja.frame import TrajaDataFrame +from traja.core import is_datetime_or_timedelta_dtype from traja.trajectory import coords_to_flow __all__ = [ diff --git a/traja/trajectory.py b/traja/trajectory.py index 51f672e1..26a4d320 100644 --- a/traja/trajectory.py +++ b/traja/trajectory.py @@ -6,7 +6,6 @@ import numpy as np import pandas as pd from pandas.core.dtypes.common import ( - is_datetime_or_timedelta_dtype, is_datetime64_any_dtype, is_timedelta64_dtype, ) @@ -15,6 +14,7 @@ import traja from traja import TrajaDataFrame +from traja.core import is_datetime_or_timedelta_dtype __all__ = [ "_bins_to_tuple", From 22e39b0e73b568a05b3119318a6a76d60556254e Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 19:36:26 +0100 Subject: [PATCH 09/21] Replace np.float with float --- traja/parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traja/parsers.py b/traja/parsers.py index 4135464a..e5414ec0 100644 --- a/traja/parsers.py +++ b/traja/parsers.py @@ -102,7 +102,7 @@ def read_file( converters = {**stripped_cols, **kwargs.pop("converters", {})} # Downcast to float32 # TODO: Benchmark float32 vs float64 for very big dataset - float_cols = df_test.select_dtypes(include=[np.float]).columns + float_cols = df_test.select_dtypes(include=[float]).columns float32_cols = {c: np.float32 for c in float_cols} # Convert string columns to sequence_ids From 963b4b853c65c4dc73a45c53101aafb322532397 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 19:42:24 +0100 Subject: [PATCH 10/21] Fix deprecated numpy arguments --- traja/dataset/example.py | 2 +- traja/plotting.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/traja/dataset/example.py b/traja/dataset/example.py index 32ad890e..3f8b9867 100644 --- a/traja/dataset/example.py +++ b/traja/dataset/example.py @@ -6,5 +6,5 @@ def jaguar(cache_url=default_cache_url): # Sample data data_url = "https://raw.githubusercontent.com/traja-team/traja-research/dataset_und_notebooks/dataset_analysis/jaguar5.csv" - df = pd.read_csv(data_url, error_bad_lines=False) + df = pd.read_csv(data_url, on_bad_lines='skip') return df diff --git a/traja/plotting.py b/traja/plotting.py index bb9fc6e0..c4ab66df 100644 --- a/traja/plotting.py +++ b/traja/plotting.py @@ -967,7 +967,7 @@ def trip_grid( x, y = zip(*df.values) hist, x_edges, y_edges = np.histogram2d( - x, y, bins, range=((xmin, xmax), (ymin, ymax)), normed=normalize + x, y, bins, range=((xmin, xmax), (ymin, ymax)), density=normalize ) # rotate to keep y as first dimension From aea1b0a1e98e145424b825b2f9666e404fdccac4 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 19:50:19 +0100 Subject: [PATCH 11/21] Fix deprecated gca argument --- traja/plotting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traja/plotting.py b/traja/plotting.py index c4ab66df..b5b69871 100644 --- a/traja/plotting.py +++ b/traja/plotting.py @@ -814,7 +814,7 @@ def plot_surface( Z = np.sqrt(U * U + V * V) fig = plt.figure() - ax = fig.gca(projection="3d") + ax = fig.add_subplot(projection='3d') ax.plot_surface( X, Y, Z, cmap= cmap, linewidth=0, **surfaceplot_kws ) From 13c4dd95096f7b772bb34a21a08944d7d1a1984b Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:14:28 +0100 Subject: [PATCH 12/21] Test with Python 3.12 --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 174240c3..b5651f88 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,7 +14,7 @@ jobs: strategy: matrix: os: ["ubuntu-latest", "windows-latest"] - python-version: [ "3.8", "3.9" ] + python-version: [ "3.8", "3.12" ] steps: - uses: actions/checkout@v2 - name: Set up Miniconda ${{ matrix.python-version }} From da2ad51124a0103543de6828ed0e9f500579fc35 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:23:20 +0100 Subject: [PATCH 13/21] Update pytest version --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index c959db94..cf2c18be 100644 --- a/environment.yml +++ b/environment.yml @@ -21,7 +21,7 @@ dependencies: - networkx - seaborn - pytorch - - pytest==6.2.2 + - pytest>=8.0.0 - numba>=0.50.0 - pyDOE2>=1.3.0 - statsmodels \ No newline at end of file From 928c29d28b383c3b0d07c66652ff910094b20950 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:32:50 +0100 Subject: [PATCH 14/21] Remove pyDOE --- environment.yml | 1 - requirements/extra.txt | 3 +- traja/dataset/pituitary_gland.py | 151 ------------------------------- 3 files changed, 1 insertion(+), 154 deletions(-) delete mode 100644 traja/dataset/pituitary_gland.py diff --git a/environment.yml b/environment.yml index cf2c18be..56adce84 100644 --- a/environment.yml +++ b/environment.yml @@ -23,5 +23,4 @@ dependencies: - pytorch - pytest>=8.0.0 - numba>=0.50.0 - - pyDOE2>=1.3.0 - statsmodels \ No newline at end of file diff --git a/requirements/extra.txt b/requirements/extra.txt index 1c22641e..13d86760 100644 --- a/requirements/extra.txt +++ b/requirements/extra.txt @@ -5,5 +5,4 @@ h5py ipython pre-commit h5py -numba>=0.50.1 -pyDOE2>=1.3.0 \ No newline at end of file +numba>=0.50.1 \ No newline at end of file diff --git a/traja/dataset/pituitary_gland.py b/traja/dataset/pituitary_gland.py deleted file mode 100644 index ed6c9e63..00000000 --- a/traja/dataset/pituitary_gland.py +++ /dev/null @@ -1,151 +0,0 @@ -import numpy as np -import pandas as pd -from numpy import exp -from numba import jit -from scipy.integrate import odeint -from pyDOE2 import lhs - - -# PyTest will not compute coverage correctly for @jit-compiled code. -# Thus we must explicitly suppress the coverage check. -@jit -def pituitary_ode(w, t, p): # pragma: no cover - """ - Defines the differential equations for the pituirary gland system. - To be used with scipy.integrate.odeint (this is the rhs equation). - - Arguments: - w : vector of the state variables: - w = [v, n, f, c] - t : time - p : vector of the parameters: - p = [gk, gcal, gsk, gbk, gl, k] - """ - vca = 60 - vk = -75 - vl = -50 - Cm = 10 - vn = -5 - vm = -20 - vf = -20 - sn = 10 - sm = 12 - sf = 2 - taun = 30 - taubk = 5 - ff = 0.01 - alpha = 0.0015 - ks = 0.4 - auto = 0 - cpar = 0 - noise = 4.0 - - v, n, f, c = w - - gk, gcal, gsk, gbk, gl, kc = p - - cd = (1 - auto) * c + auto * cpar - - phik = 1 / (1 + exp((vn - v) / sn)) - phif = 1 / (1 + exp((vf - v) / sf)) - phical = 1 / (1 + exp((vm - v) / sm)) - cinf = cd ** 2 / (cd ** 2 + ks ** 2) - - ica = gcal * phical * (v - vca) - isk = gsk * cinf * (v - vk) - ibk = gbk * f * (v - vk) - ikdr = gk * n * (v - vk) - ileak = gl * (v - vl) - - ikdrx = ikdr - ibkx = ibk - - ik = isk + ibk + ikdr - inoise = 0 # noise*w #TODO fix - - dv = -(ica + ik + inoise + ileak) / Cm - dn = (phik - n) / taun - df = (phif - f) / taubk - dc = -ff * (alpha * ica + kc * c) - return dv, dn, df, dc - - -def compute_pituitary_gland_df_from_parameters(downsample_rate, - gcal, gsk, gk, gbk, gl, kc, - sample_id, - trim_start=20000): - """ - Computes a Traja dataframe from the pituitary gland simulation. - - It is easier to discuss ion flow in term of conductances than resistances. - If V / R = I, where V is the voltage, R is the resistance and I is the - current, then V * C = I, where C = 1 / R is the conductance. - - Below we specify arguments in terms of maximum conductances, - i.e. the maximum rate at which ion channels let ions through - the cell walls. - - Arguments: - downsample_rate : How much the dataframe will be downsampled (relative - to the original simulation) - gcal : The maximum calcium conductance - gsk : The maximum s-potassiun conductance - gk : The maximum potassium conductance - gbk : The maximum b-potassium conductance - gl : The maximum leak conductance - kc : - sample_id : The ID of this particular sample. Must be unique - trim_start : How much of the start of the sample to trim. - The start of an activation (before converging to a limit cycle - or fixed point) is usually not interesting from a biological - perspective, so the default is to remove it. - """ - - # Initial conditions - v = -60. - n = 0.1 - f = 0.01 - c = 0.1 - - p = (gk, gcal, gsk, gbk, gl, kc) - w0 = (v, n, f, c) - abserr = 1.0e-8 - relerr = 1.0e-6 - - t = np.arange(0, 5000, 0.05) - # print("Generating gcal={}, gsk={}, gk={}, gbk={}, gl={}, kc={}".format(gcal, gsk, gk, gbk, gl, kc)) - wsol = odeint(pituitary_ode, w0, t, args=(p,), atol=abserr, rtol=relerr) - df = pd.DataFrame(wsol, columns=['v', 'n', 'f', 'c']) - df = df[trim_start:] - df['ID'] = sample_id - df['gcal'] = gcal - df['gsk'] = gsk - df['gk'] = gk - df['gbk'] = gbk - df['gl'] = gl - df['kc'] = kc - df = df.iloc[::downsample_rate, :] - # df = df.drop(columns=['t', 'ikdrx', 'ibkx']) - - return df - - -def create_latin_hypercube_sampled_pituitary_df(downsample_rate=100, samples=1000): - latin_hypercube_samples = lhs(6, criterion='center', samples=samples) - - # gcal, gsk, gk, gbk, gl, kc, - range_start = (0.5, 0.5, 0.8, 0., 0.05, 0.03) - range_end = (3.5, 3.5, 5.6, 4., 0.35, 0.21) - - parameters = latin_hypercube_samples * range_end - latin_hypercube_samples * range_start - - dataframes = [] - for sample_id, parameter in enumerate(parameters): - gcal, gsk, gk, gbk, gl, kc = parameter - df = compute_pituitary_gland_df_from_parameters(downsample_rate, - gcal, gsk, gk, gbk, gl, kc, - sample_id) - dataframes.append(df) - - num_samples = len(dataframes) - return pd.concat(dataframes), num_samples From d14b057b01678233e5fd25a46971129dae135741 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:36:52 +0100 Subject: [PATCH 15/21] Remove redundant tests --- traja/tests/test_dataset.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/traja/tests/test_dataset.py b/traja/tests/test_dataset.py index 7b2daa00..101fd85e 100644 --- a/traja/tests/test_dataset.py +++ b/traja/tests/test_dataset.py @@ -3,7 +3,6 @@ import pytest from traja.dataset import dataset -from traja.dataset.pituitary_gland import create_latin_hypercube_sampled_pituitary_df @pytest.mark.skipif(os.name == 'nt', reason="hangs on Windows for unknown reason") @@ -646,10 +645,3 @@ def test_sequential_data_loader_indices_are_sequential(): assert ( id == current_id ), "IDs in sequential test loader should increase monotonically!" - - -def test_pituitary_gland_latin_hypercube_generator_gives_correct_number_of_samples(): - num_samples = 30 - _, num_samples_out = create_latin_hypercube_sampled_pituitary_df(samples=num_samples) - - assert num_samples == num_samples_out, "Hypercube sampler returned the wrong number of samples!" From ffb60c13a4ba3cd2f3d556bd3f4e1c3cd6ee35ed Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:49:14 +0100 Subject: [PATCH 16/21] Apply Black formatter and remove slow tests on mac --- traja/contrib/rdp.py | 1 + traja/core.py | 5 +- traja/dataset/dataset.py | 1 + traja/dataset/example.py | 2 +- traja/frame.py | 10 +- traja/models/inference.py | 1 + traja/models/losses.py | 3 +- traja/models/optimizers.py | 2 - traja/models/predictive_models/lstm.py | 11 +- traja/models/train.py | 14 +- traja/models/utils.py | 8 +- traja/plotting.py | 74 +++-- traja/stats/brownian.py | 12 +- traja/tests/test_dataset.py | 121 +++---- traja/tests/test_models.py | 425 +++++++++++++++++-------- traja/tests/test_stats.py | 11 +- traja/trajectory.py | 18 +- 17 files changed, 441 insertions(+), 278 deletions(-) diff --git a/traja/contrib/rdp.py b/traja/contrib/rdp.py index e00c4179..89a99550 100644 --- a/traja/contrib/rdp.py +++ b/traja/contrib/rdp.py @@ -19,6 +19,7 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. """ + from functools import partial from typing import Union, Callable diff --git a/traja/core.py b/traja/core.py index ec274fe0..e3f7fc28 100644 --- a/traja/core.py +++ b/traja/core.py @@ -1,5 +1,8 @@ import pandas as pd + # Check whether pandas series is datetime or timedelta def is_datetime_or_timedelta_dtype(series: pd.Series) -> bool: - return pd.api.types.is_datetime64_dtype(series) or pd.api.types.is_timedelta64_dtype(series) \ No newline at end of file + return pd.api.types.is_datetime64_dtype( + series + ) or pd.api.types.is_timedelta64_dtype(series) diff --git a/traja/dataset/dataset.py b/traja/dataset/dataset.py index 3a8e1413..5822b13e 100644 --- a/traja/dataset/dataset.py +++ b/traja/dataset/dataset.py @@ -11,6 +11,7 @@ 1. Class distribution in the dataset """ + import logging import math from collections import defaultdict diff --git a/traja/dataset/example.py b/traja/dataset/example.py index 3f8b9867..fb3ca9c2 100644 --- a/traja/dataset/example.py +++ b/traja/dataset/example.py @@ -6,5 +6,5 @@ def jaguar(cache_url=default_cache_url): # Sample data data_url = "https://raw.githubusercontent.com/traja-team/traja-research/dataset_und_notebooks/dataset_analysis/jaguar5.csv" - df = pd.read_csv(data_url, on_bad_lines='skip') + df = pd.read_csv(data_url, on_bad_lines="skip") return df diff --git a/traja/frame.py b/traja/frame.py index 9c60c872..f210d09d 100644 --- a/traja/frame.py +++ b/traja/frame.py @@ -54,13 +54,13 @@ def __init__(self, *args, **kwargs): args[0]._copy_attrs(self) for name, value in traja_kwargs.items(): self.__dict__[name] = value - - # Initialize + + # Initialize self._convex_hull = None # Initialize metadata like 'fps','spatial_units', etc. self._init_metadata() - + @property def _constructor(self): return TrajaDataFrame @@ -171,7 +171,7 @@ def center(self): x = self.x y = self.y return float(x.mean()), float(y.mean()) - + @property def convex_hull(self): """Property of TrajaDataFrame class representing @@ -179,7 +179,7 @@ def convex_hull(self): """ # Calculate if it doesn't exist - if self._convex_hull is None: + if self._convex_hull is None: xy_arr = self.traja.xy point_arr = traja.trajectory.calc_convex_hull(xy_arr) self._convex_hull = point_arr diff --git a/traja/models/inference.py b/traja/models/inference.py index 2bab46f1..f72defef 100644 --- a/traja/models/inference.py +++ b/traja/models/inference.py @@ -134,6 +134,7 @@ def generate(self, num_steps, classify=True, scaler=None, plot_data=True): elif self.model_type == "vaegan" or "custom": return NotImplementedError + class Predictor: def __init__( self, diff --git a/traja/models/losses.py b/traja/models/losses.py index e0b51752..4dc025ed 100644 --- a/traja/models/losses.py +++ b/traja/models/losses.py @@ -2,6 +2,7 @@ device = "cuda" if torch.cuda.is_available() else "cpu" + class Criterion: """Implements the loss functions of Autoencoders, Variational Autoencoders and LSTM models Huber loss is set as default for reconstruction loss, alternative is to use rmse, @@ -30,7 +31,7 @@ def forecasting_criterion( """ if mu is not None and logvar is not None: - kld = -0.5 * torch.sum(1 + logvar - mu ** 2 - logvar.exp()) + kld = -0.5 * torch.sum(1 + logvar - mu**2 - logvar.exp()) else: kld = 0 diff --git a/traja/models/optimizers.py b/traja/models/optimizers.py index b967583a..d7fbdc34 100644 --- a/traja/models/optimizers.py +++ b/traja/models/optimizers.py @@ -4,7 +4,6 @@ class Optimizer: def __init__(self, model_type, model, optimizer_type, classify=False): - """ Wrapper for setting the model optimizer and learning rate schedulers using ReduceLROnPlateau; If the model type is 'ae' or 'vae' - var optimizers is a dict with separate optimizers for encoder, decoder, @@ -94,7 +93,6 @@ def get_optimizers(self, lr=0.0001): return forecasting_optimizers, classification_optimizers, regression_optimizers def get_lrschedulers(self, factor: float, patience: int): - """Learning rate scheduler for each network in the model NOTE: Scheduler metric should be test set loss diff --git a/traja/models/predictive_models/lstm.py b/traja/models/predictive_models/lstm.py index 1df554e0..aae1cb0d 100644 --- a/traja/models/predictive_models/lstm.py +++ b/traja/models/predictive_models/lstm.py @@ -1,4 +1,5 @@ """Implementation of Multimodel LSTM""" + import torch from traja.models.utils import TimeDistributed @@ -14,7 +15,7 @@ class LSTM(torch.nn.Module): hidden_size: The number of features in the hidden state ``h`` output_size: The number of output dimensions batch_size: Size of batch. Default is 8 - sequence_length: The number of in each sample + sequence_length: The number of in each sample num_layers: Number of recurrent layers. E.g., setting ``num_layers=2`` would mean stacking two LSTMs together to form a `stacked LSTM`, with the second LSTM taking in outputs of the first LSTM and @@ -27,13 +28,13 @@ class LSTM(torch.nn.Module): """ def __init__( - self, - input_size: int, + self, + input_size: int, hidden_size: int, output_size: int, num_future: int = 8, batch_size: int = 8, - num_layers: int = 1, + num_layers: int = 1, reset_state: bool = True, bidirectional: bool = False, dropout: float = 0, @@ -47,7 +48,7 @@ def __init__( self.num_future = num_future self.hidden_size = hidden_size self.num_layers = num_layers - self.output_size = output_size + self.output_size = output_size self.dropout = dropout self.batch_first = batch_first self.reset_state = reset_state diff --git a/traja/models/train.py b/traja/models/train.py index 4c753d56..2e4da99a 100644 --- a/traja/models/train.py +++ b/traja/models/train.py @@ -131,7 +131,13 @@ def __str__(self): return f"Training model type {self.model_type}" def fit( - self, dataloaders, model_save_path=None, training_mode="forecasting", epochs=50, test_every=10, validate_every=None + self, + dataloaders, + model_save_path=None, + training_mode="forecasting", + epochs=50, + test_every=10, + validate_every=None, ): """ This method implements the batch- wise training and testing protocol for both time series forecasting and @@ -161,8 +167,8 @@ def fit( train_loader = dataloaders["train_loader"] test_loader = dataloaders["test_loader"] - if 'validation_loader' in dataloaders: - validation_loader = dataloaders['validation_loader'] + if "validation_loader" in dataloaders: + validation_loader = dataloaders["validation_loader"] else: validate_every = None @@ -273,7 +279,7 @@ def fit( correct = 0.0 self.model.eval() for idx, (data, target, ids, parameters, classes) in enumerate( - data_loader_to_evaluate + data_loader_to_evaluate ): if type(ids) == list: ids = ids[0] diff --git a/traja/models/utils.py b/traja/models/utils.py index 2680f2ab..cf32855b 100644 --- a/traja/models/utils.py +++ b/traja/models/utils.py @@ -5,7 +5,7 @@ class TimeDistributed(torch.nn.Module): - """ Time distributed wrapper compatible with linear/dense pytorch layer modules""" + """Time distributed wrapper compatible with linear/dense pytorch layer modules""" def __init__(self, module, batch_first=True): super(TimeDistributed, self).__init__() @@ -37,7 +37,7 @@ def forward(self, x): return out -def save(model, hyperparameters, path:str=""): +def save(model, hyperparameters, path: str = ""): """Save the trained model(.pth) along with its hyperparameters as a json (hyper.json) at the user defined Path Parameters: ----------- @@ -55,7 +55,7 @@ def save(model, hyperparameters, path:str=""): if path == "": path = os.path.join(os.getcwd(), "model.pt") torch.save(model.state_dict(), path) - + hyperdir, _ = os.path.split(path) if hyperparameters is not None: with open(os.path.join(hyperdir, "hypers.json"), "w") as fp: @@ -65,7 +65,7 @@ def save(model, hyperparameters, path:str=""): print(f"Model and hyperparameters saved at {os.path.abspath(hyperdir)}") -def load(model, path: str=""): +def load(model, path: str = ""): """Load trained model from path using the model_hyperparameters saved in the Parameters: ----------- diff --git a/traja/plotting.py b/traja/plotting.py index b5b69871..f7b4ef80 100644 --- a/traja/plotting.py +++ b/traja/plotting.py @@ -43,8 +43,8 @@ "plot_clustermap", "plot_flow", "plot_pca", - "plot_periodogram", - "plot_quiver", + "plot_periodogram", + "plot_quiver", "plot_stream", "plot_surface", "plot_transition_graph", @@ -496,7 +496,7 @@ def plot_periodogram(trj, coord: str = "y", fs: int = 1, interactive: bool = Tru trj = traja.generate() trj.traja.plot_periodogram() - .. note:: + .. note:: Convenience wrapper for :meth:`scipy.signal.periodogram`. @@ -535,7 +535,7 @@ def plot_autocorrelation( .. plot:: import traja - + df = traja.generate() df.traja.plot_autocorrelation() @@ -552,9 +552,15 @@ def plot_autocorrelation( return plt.gcf() -def plot_pca(trj: TrajaDataFrame, id_col: str="id", bins: tuple = (8,8), three_dims: bool = False, ax = None): +def plot_pca( + trj: TrajaDataFrame, + id_col: str = "id", + bins: tuple = (8, 8), + three_dims: bool = False, + ax=None, +): """Plot PCA comparing animals ids by trip grids. - + Args: trj - Trajectory id_col - column representing animal IDs @@ -564,20 +570,19 @@ def plot_pca(trj: TrajaDataFrame, id_col: str="id", bins: tuple = (8,8), three_d Returns: fig - Figure - + .. plot:: # Load sample jaguar dataset with trajectories for 9 animals df = traja.dataset.example.jaguar() # Bin trajectory into a trip grid then perform PCA - traja.plotting.plot_pca(df, id_col="ID", bins=(8,8)) + traja.plotting.plot_pca(df, id_col="ID", bins=(8,8)) """ from sklearn.decomposition import PCA from sklearn.preprocessing import StandardScaler - DIMS = 3 if three_dims else 2 # Bin trajectories to trip grids @@ -585,9 +590,9 @@ def plot_pca(trj: TrajaDataFrame, id_col: str="id", bins: tuple = (8,8), three_d ids = trj[id_col].unique() for id in ids: - animal = trj[trj[id_col]==id].copy() - animal.drop(columns=[id_col],inplace=True) - grid = animal.traja.trip_grid(bins = bins, hist_only=True)[0] + animal = trj[trj[id_col] == id].copy() + animal.drop(columns=[id_col], inplace=True) + grid = animal.traja.trip_grid(bins=bins, hist_only=True)[0] grids.append(grid.flatten()) # Standardize the data @@ -601,24 +606,35 @@ def plot_pca(trj: TrajaDataFrame, id_col: str="id", bins: tuple = (8,8), three_d # Create plot axes if DIMS == 3: fig = plt.figure() - ax = fig.add_subplot(111, projection='3d') + ax = fig.add_subplot(111, projection="3d") if not ax: _, ax = plt.subplots() - + # Visualize 2D projection for idx, animal in enumerate(X_r): if DIMS == 2: - ax.scatter(X_r[idx, 0], X_r[idx, 1], color=f'C{idx}', alpha=.8, lw=2, label=idx) + ax.scatter( + X_r[idx, 0], X_r[idx, 1], color=f"C{idx}", alpha=0.8, lw=2, label=idx + ) elif DIMS == 3: - ax.scatter(X_r[idx, 0], X_r[idx, 1], ax.scatter[idx,2], color=f'C{idx}', alpha=.8, lw=2, label=idx) + ax.scatter( + X_r[idx, 0], + X_r[idx, 1], + ax.scatter[idx, 2], + color=f"C{idx}", + alpha=0.8, + lw=2, + label=idx, + ) plt.title("PCA") - plt.legend(title=id_col, loc='best', shadow=False, scatterpoints=1) + plt.legend(title=id_col, loc="best", shadow=False, scatterpoints=1) plt.xlabel("Principal Component 1") - plt.ylabel("Principal Component 2") + plt.ylabel("Principal Component 2") return plt.gcf() + def plot_collection( trjs: Union[pd.DataFrame, TrajaDataFrame], id_col: str = "id", @@ -771,7 +787,7 @@ def plot_contour( X, Y, U, V = coords_to_flow(trj, bins) Z = np.sqrt(U * U + V * V) - if not ax: + if not ax: _, ax = plt.subplots() if filled: @@ -814,10 +830,8 @@ def plot_surface( Z = np.sqrt(U * U + V * V) fig = plt.figure() - ax = fig.add_subplot(projection='3d') - ax.plot_surface( - X, Y, Z, cmap= cmap, linewidth=0, **surfaceplot_kws - ) + ax = fig.add_subplot(projection="3d") + ax.plot_surface(X, Y, Z, cmap=cmap, linewidth=0, **surfaceplot_kws) ax = _label_axes(trj, ax) try: @@ -1388,8 +1402,8 @@ def animate(trj: TrajaDataFrame, polar: bool = True, save: bool = False): save (bool): save video to ``trajectory.mp4`` Returns: - anim (matplotlib.animation.FuncAnimation): animation - + anim (matplotlib.animation.FuncAnimation): animation + """ from matplotlib import animation from matplotlib.animation import FuncAnimation @@ -1407,7 +1421,7 @@ def animate(trj: TrajaDataFrame, polar: bool = True, save: bool = False): fig = plt.figure(figsize=(8, 6)) ax1 = plt.subplot(211) - fig.add_subplot(ax1) + fig.add_subplot(ax1) if polar: ax2 = plt.subplot(212, polar="projection") ax2.set_theta_zero_location("N") @@ -1435,7 +1449,7 @@ def animate(trj: TrajaDataFrame, polar: bool = True, save: bool = False): ) def update(frame_number): - if frame_number < (XY_STEPS+2): + if frame_number < (XY_STEPS + 2): pass else: ind = frame_number % len(xy) @@ -1482,7 +1496,9 @@ def update(frame_number): bar.set_facecolor(plt.cm.viridis(h / max_height)) bar.set_alpha(0.8 * (idx / POLAR_STEPS)) ax2.set_theta_zero_location("N") - ax2.set_xticklabels(["0", "45", "90", "135", "180", "-135", "-90", "-45"]) + ax2.set_xticklabels( + ["0", "45", "90", "135", "180", "-135", "-90", "-45"] + ) anim = FuncAnimation(fig, update, interval=10, frames=len(xy)) if save: @@ -1492,5 +1508,5 @@ def update(frame_number): raise Exception("FFmpeg not installed, please install it.") else: plt.show() - + return anim diff --git a/traja/stats/brownian.py b/traja/stats/brownian.py index c198ad6d..79b43952 100644 --- a/traja/stats/brownian.py +++ b/traja/stats/brownian.py @@ -22,8 +22,10 @@ class Brownian: dt: delta-time between every step. """ - def __init__(self, x0=0, mean_value=0, variance=1, dt=1., length=100000): - assert (type(x0) == float or type(x0) == int or x0 is None), "Expect a float or None for the initial value" + def __init__(self, x0=0, mean_value=0, variance=1, dt=1.0, length=100000): + assert ( + type(x0) == float or type(x0) == int or x0 is None + ), "Expect a float or None for the initial value" self._x0 = float(x0) @@ -42,7 +44,11 @@ def _generate_noise(self): x0 = np.asarray(self._x0) # Generate self._length samples of noise - r = norm.rvs(loc=self._mean_value, scale=self._variance * np.sqrt(self._dt), size=self._length) + r = norm.rvs( + loc=self._mean_value, + scale=self._variance * np.sqrt(self._dt), + size=self._length, + ) out = np.empty(r.shape) # This computes the Brownian motion by forming the cumulative sum of diff --git a/traja/tests/test_dataset.py b/traja/tests/test_dataset.py index 101fd85e..1081b44c 100644 --- a/traja/tests/test_dataset.py +++ b/traja/tests/test_dataset.py @@ -1,11 +1,14 @@ -import os +import sys import pandas as pd import pytest from traja.dataset import dataset -@pytest.mark.skipif(os.name == 'nt', reason="hangs on Windows for unknown reason") +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_time_based_sampling_dataloaders_do_not_overlap(): data = list() num_ids = 140 @@ -48,85 +51,27 @@ def test_time_based_sampling_dataloaders_do_not_overlap(): for data, target, ids, parameters, classes in dataloaders["train_loader"]: for sequence in data: - assert all(sample == -1.0 for sample in sequence[:,0]) + assert all(sample == -1.0 for sample in sequence[:, 0]) for sequence in target: - assert all(sample == -1.0 for sample in sequence[:,0]) + assert all(sample == -1.0 for sample in sequence[:, 0]) for data, target, ids, parameters, classes in dataloaders["test_loader"]: for sequence in data: - assert all(sample == 0 for sample in sequence[:,0]) + assert all(sample == 0 for sample in sequence[:, 0]) for sequence in target: - assert all(sample == 0 for sample in sequence[:,0]) + assert all(sample == 0 for sample in sequence[:, 0]) for data, target, ids, parameters, classes in dataloaders["validation_loader"]: for sequence in data: - assert all(sample == 1 for sample in sequence[:,0]) + assert all(sample == 1 for sample in sequence[:, 0]) for sequence in target: - assert all(sample == 1 for sample in sequence[:,0]) + assert all(sample == 1 for sample in sequence[:, 0]) -def test_time_based_sampling_dataloaders_do_not_overlap(): - data = list() - num_ids = 140 - sequence_length = 2000 - - # Hyperparameters - batch_size = 15 - num_past = 10 - num_future = 5 - train_split_ratio = 0.498 - validation_split_ratio = 0.25 - - stride = 5 - - split_by_id = False # The test condition - - # The train[0] column should contain only 1s, the test column should contain 2s and the - # validation column set should contain 3s. - # When scaled, this translates to -1., 0 and 1. respectively. - for sample_id in range(num_ids): - for element in range(round(sequence_length * train_split_ratio) - 6): - data.append([1, element, sample_id]) - for element in range( - round(sequence_length * (1 - train_split_ratio - validation_split_ratio)) - + -4 - ): - data.append([2, element, sample_id]) - for element in range(round(sequence_length * validation_split_ratio) + 10): - data.append([3, element, sample_id]) - - df = pd.DataFrame(data, columns=["x", "y", "ID"]) - - dataloaders = dataset.MultiModalDataLoader( - df, - batch_size=batch_size, - n_past=num_past, - n_future=num_future, - num_workers=1, - train_split_ratio=train_split_ratio, - validation_split_ratio=validation_split_ratio, - split_by_id=split_by_id, - stride=stride, - ) - - for data, target, ids, parameters, classes in dataloaders["train_loader"]: - for sequence in data: - assert all(sample == -1. for sample in sequence[:,0]) - for sequence in target: - assert all(sample == -1. for sample in sequence[:,0]) - - for data, target, ids, parameters, classes in dataloaders["test_loader"]: - for sequence in data: - assert all(sample == 0 for sample in sequence[:,0]) - for sequence in target: - assert all(sample == 0 for sample in sequence[:,0]) - - for data, target, ids, parameters, classes in dataloaders["validation_loader"]: - for sequence in data: - assert all(sample == 1 for sample in sequence[:,0]) - for sequence in target: - assert all(sample == 1 for sample in sequence[:,0]) - +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_time_based_sampling_dataloaders_with_stride_one_do_not_overlap(): data = list() num_ids = 2 @@ -173,23 +118,27 @@ def test_time_based_sampling_dataloaders_with_stride_one_do_not_overlap(): for data, target, ids, parameters, classes in dataloaders["train_loader"]: for sequence in data: - assert all(sample == -1. for sample in sequence[:,0]) + assert all(sample == -1.0 for sample in sequence[:, 0]) for sequence in target: - assert all(sample == -1. for sample in sequence[:,0]) + assert all(sample == -1.0 for sample in sequence[:, 0]) for data, target, ids, parameters, classes in dataloaders["test_loader"]: for sequence in data: - assert all(sample == 0 for sample in sequence[:,0]) + assert all(sample == 0 for sample in sequence[:, 0]) for sequence in target: - assert all(sample == 0 for sample in sequence[:,0]) + assert all(sample == 0 for sample in sequence[:, 0]) for data, target, ids, parameters, classes in dataloaders["validation_loader"]: for sequence in data: - assert all(sample == 1 for sample in sequence[:,0]) + assert all(sample == 1 for sample in sequence[:, 0]) for sequence in target: - assert all(sample == 1 for sample in sequence[:,0]) + assert all(sample == 1 for sample in sequence[:, 0]) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_time_based_weighted_sampling_dataloaders_do_not_overlap(): data = list() num_ids = 232 @@ -246,6 +195,10 @@ def test_time_based_weighted_sampling_dataloaders_do_not_overlap(): ) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_id_wise_sampling_with_few_ids_does_not_put_id_in_multiple_dataloaders(): data = list() num_ids = 5 @@ -281,6 +234,10 @@ def test_id_wise_sampling_with_few_ids_does_not_put_id_in_multiple_dataloaders() ) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_id_wise_sampling_with_short_sequences_does_not_divide_by_zero(): data = list() num_ids = 283 @@ -322,6 +279,10 @@ def test_id_wise_sampling_with_short_sequences_does_not_divide_by_zero(): ) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_id_wise_sampling_does_not_put_id_in_multiple_dataloaders(): data = list() num_ids = 150 @@ -357,6 +318,10 @@ def test_id_wise_sampling_does_not_put_id_in_multiple_dataloaders(): ) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_id_wise_weighted_sampling_does_not_put_id_in_multiple_dataloaders(): data = list() num_ids = 150 @@ -595,6 +560,10 @@ def verify_that_indices_belong_to_precisely_one_loader( ), f"Index {index} is in both the test and validation loaders!" +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_sequential_data_loader_indices_are_sequential(): data = list() num_ids = 46 diff --git a/traja/tests/test_models.py b/traja/tests/test_models.py index 61a9f157..2ba023e3 100644 --- a/traja/tests/test_models.py +++ b/traja/tests/test_models.py @@ -8,8 +8,14 @@ from traja.models import MultiModelAE from traja.models import MultiModelVAE from traja.models.train import HybridTrainer +import sys +import pytest +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_aevae_jaguar(): """ Test variational autoencoder forecasting with the Jaguar dataset @@ -59,7 +65,14 @@ def test_aevae_jaguar(): trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="huber") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=1, training_mode="forecasting", validate_every=5, test_every=10) + trainer.fit( + data_loaders, + model_save_path, + epochs=1, + training_mode="forecasting", + validate_every=5, + test_every=10, + ) scaler = data_loaders["train_loader"].dataset.scaler @@ -80,6 +93,10 @@ def test_aevae_jaguar(): trainer.validate(data_loaders["validation_loader"]) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_ae_jaguar(): """ Test autoencoder forecasting with the Jaguar dataset @@ -125,13 +142,38 @@ def test_ae_jaguar(): trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="huber") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=1, training_mode="forecasting", validate_every=2, test_every=5) - trainer.fit(data_loaders, model_save_path, epochs=1, training_mode="forecasting", validate_every=None, test_every=5) - trainer.fit(data_loaders, model_save_path, epochs=1, training_mode="forecasting", validate_every=2, test_every=None) + trainer.fit( + data_loaders, + model_save_path, + epochs=1, + training_mode="forecasting", + validate_every=2, + test_every=5, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=1, + training_mode="forecasting", + validate_every=None, + test_every=5, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=1, + training_mode="forecasting", + validate_every=2, + test_every=None, + ) trainer.validate(data_loaders["sequential_validation_loader"]) +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_lstm_jaguar(): """ Testing method for lstm model used for forecasting. @@ -170,22 +212,33 @@ def test_lstm_jaguar(): ) # Model Trainer - trainer = HybridTrainer(model=model, - optimizer_type='Adam', - loss_type='huber') + trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="huber") - forecasting_loss_pre_training, _, _ = trainer.validate(data_loaders['train_loader']) - print(f'Loss pre training: {forecasting_loss_pre_training}') + forecasting_loss_pre_training, _, _ = trainer.validate(data_loaders["train_loader"]) + print(f"Loss pre training: {forecasting_loss_pre_training}") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="forecasting", validate_every=1, test_every=2) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="forecasting", + validate_every=1, + test_every=2, + ) - forecasting_loss_post_training, _, _ = trainer.validate(data_loaders['train_loader']) + forecasting_loss_post_training, _, _ = trainer.validate( + data_loaders["train_loader"] + ) - print(f'Loss post training: {forecasting_loss_post_training}') + print(f"Loss post training: {forecasting_loss_post_training}") assert forecasting_loss_post_training < forecasting_loss_pre_training +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_aevae_regression_network_converges(): """ Test Autoencoder and variational auto encoder models for training/testing/generative network and @@ -251,20 +304,38 @@ def test_aevae_regression_network_converges(): # Model types; "ae" or "vae" trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="mse") - _, regression_lost_pre_training, _ = trainer.validate(data_loaders['train_loader']) + _, regression_lost_pre_training, _ = trainer.validate(data_loaders["train_loader"]) - print(f'Loss pre training: {regression_lost_pre_training}') + print(f"Loss pre training: {regression_lost_pre_training}") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="forecasting", validate_every=1, test_every=2) - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="regression", validate_every=1, test_every=2) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="forecasting", + validate_every=1, + test_every=2, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="regression", + validate_every=1, + test_every=2, + ) - _, regression_lost_post_training, _ = trainer.validate(data_loaders['train_loader']) + _, regression_lost_post_training, _ = trainer.validate(data_loaders["train_loader"]) - print(f'Loss post training: {regression_lost_post_training}') + print(f"Loss post training: {regression_lost_post_training}") assert regression_lost_post_training < regression_lost_pre_training +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_ae_regression_network_converges(): """ Test that Autoencoder and variational auto encoder models for regression networks converge @@ -288,58 +359,78 @@ def test_ae_regression_network_converges(): num_past = 10 num_future = 5 # Prepare the dataloader - data_loaders = dataset.MultiModalDataLoader(df, - batch_size=batch_size, - n_past=num_past, - n_future=num_future, - train_split_ratio=0.333, - validation_split_ratio=0.333, - num_workers=1, - parameter_columns=parameter_columns, - split_by_id=False, - stride=1) - - model_save_path = './model.pt' - - model = MultiModelAE(input_size=2, - output_size=2, - lstm_hidden_size=32, - num_lstm_layers=2, - num_regressor_parameters=len(parameter_columns), - latent_size=10, - dropout=0.1, - num_regressor_layers=4, - regressor_hidden_size=32, - batch_size=batch_size, - num_future=num_future, - num_past=num_past, - bidirectional=False, - batch_first=True, - reset_state=True) + data_loaders = dataset.MultiModalDataLoader( + df, + batch_size=batch_size, + n_past=num_past, + n_future=num_future, + train_split_ratio=0.333, + validation_split_ratio=0.333, + num_workers=1, + parameter_columns=parameter_columns, + split_by_id=False, + stride=1, + ) + + model_save_path = "./model.pt" + + model = MultiModelAE( + input_size=2, + output_size=2, + lstm_hidden_size=32, + num_lstm_layers=2, + num_regressor_parameters=len(parameter_columns), + latent_size=10, + dropout=0.1, + num_regressor_layers=4, + regressor_hidden_size=32, + batch_size=batch_size, + num_future=num_future, + num_past=num_past, + bidirectional=False, + batch_first=True, + reset_state=True, + ) # Test resetting the regressor, to make sure this function works model.reset_regressor(regressor_hidden_size=32, num_regressor_layers=4) # Model Trainer # Model types; "ae" or "vae" - trainer = HybridTrainer(model=model, - optimizer_type='Adam', - loss_type='mse') + trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="mse") - _, regression_lost_pre_training, _ = trainer.validate(data_loaders['train_loader']) + _, regression_lost_pre_training, _ = trainer.validate(data_loaders["train_loader"]) - print(f'Loss pre training: {regression_lost_pre_training}') + print(f"Loss pre training: {regression_lost_pre_training}") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode='forecasting', validate_every=1, test_every=2) - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode='regression', validate_every=1, test_every=2) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="forecasting", + validate_every=1, + test_every=2, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="regression", + validate_every=1, + test_every=2, + ) - _, regression_lost_post_training, _ = trainer.validate(data_loaders['train_loader']) + _, regression_lost_post_training, _ = trainer.validate(data_loaders["train_loader"]) - print(f'Loss post training: {regression_lost_post_training}') + print(f"Loss post training: {regression_lost_post_training}") assert regression_lost_post_training < regression_lost_pre_training +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_vae_regression_network_converges(): """ Test that Autoencoder and variational auto encoder models for regression networks converge @@ -354,43 +445,47 @@ def test_vae_regression_network_converges(): parameter_two = 91.235 * sample_id data.append([sequence, sequence, sample_id, parameter_one, parameter_two]) # Sample data - df = pd.DataFrame(data, columns=['x', 'y', 'ID', 'parameter_one', 'parameter_two']) + df = pd.DataFrame(data, columns=["x", "y", "ID", "parameter_one", "parameter_two"]) - parameter_columns = ['parameter_one', 'parameter_two'] + parameter_columns = ["parameter_one", "parameter_two"] # Hyperparameters batch_size = 1 num_past = 10 num_future = 5 # Prepare the dataloader - data_loaders = dataset.MultiModalDataLoader(df, - batch_size=batch_size, - n_past=num_past, - n_future=num_future, - train_split_ratio=0.333, - validation_split_ratio=0.333, - num_workers=1, - parameter_columns=parameter_columns, - split_by_id=False, - stride=1) - - model_save_path = './model.pt' - - model = MultiModelVAE(input_size=2, - output_size=2, - lstm_hidden_size=32, - num_lstm_layers=2, - num_regressor_parameters=len(parameter_columns), - latent_size=10, - dropout=0.1, - num_regressor_layers=4, - regressor_hidden_size=32, - batch_size=batch_size, - num_future=num_future, - num_past=num_past, - bidirectional=False, - batch_first=True, - reset_state=True) + data_loaders = dataset.MultiModalDataLoader( + df, + batch_size=batch_size, + n_past=num_past, + n_future=num_future, + train_split_ratio=0.333, + validation_split_ratio=0.333, + num_workers=1, + parameter_columns=parameter_columns, + split_by_id=False, + stride=1, + ) + + model_save_path = "./model.pt" + + model = MultiModelVAE( + input_size=2, + output_size=2, + lstm_hidden_size=32, + num_lstm_layers=2, + num_regressor_parameters=len(parameter_columns), + latent_size=10, + dropout=0.1, + num_regressor_layers=4, + regressor_hidden_size=32, + batch_size=batch_size, + num_future=num_future, + num_past=num_past, + bidirectional=False, + batch_first=True, + reset_state=True, + ) # Test resetting the regressor, to make sure this function works model.reset_regressor(regressor_hidden_size=32, num_regressor_layers=4) @@ -399,20 +494,38 @@ def test_vae_regression_network_converges(): # Model types; "ae" or "vae" trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="mse") - _, regression_lost_pre_training, _ = trainer.validate(data_loaders['train_loader']) + _, regression_lost_pre_training, _ = trainer.validate(data_loaders["train_loader"]) - print(f'Loss pre training: {regression_lost_pre_training}') + print(f"Loss pre training: {regression_lost_pre_training}") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="forecasting", validate_every=1, test_every=2) - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="regression", validate_every=1, test_every=2) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="forecasting", + validate_every=1, + test_every=2, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="regression", + validate_every=1, + test_every=2, + ) - _, regression_lost_post_training, _ = trainer.validate(data_loaders['train_loader']) + _, regression_lost_post_training, _ = trainer.validate(data_loaders["train_loader"]) - print(f'Loss post training: {regression_lost_post_training}') + print(f"Loss post training: {regression_lost_post_training}") assert regression_lost_post_training < regression_lost_pre_training +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_ae_classification_network_converges(): """ Test that Autoencoder and variational auto encoder models for classification networks converge @@ -428,7 +541,7 @@ def test_ae_classification_network_converges(): yy = sample_class * np.cos(sequence / 20.0) + (sample_class - 1) * sequence data.append([xx, yy, sample_id, sample_class]) # Sample data - df = pd.DataFrame(data, columns=['x', 'y', 'ID', 'class']) + df = pd.DataFrame(data, columns=["x", "y", "ID", "class"]) # Hyperparameters batch_size = 2 num_past = 10 @@ -473,20 +586,42 @@ def test_ae_classification_network_converges(): # Model types; "ae" or "vae" trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="mse") - _, _, classification_loss_pre_training = trainer.validate(data_loaders['train_loader']) + _, _, classification_loss_pre_training = trainer.validate( + data_loaders["train_loader"] + ) - print(f'Loss pre training: {classification_loss_pre_training}') + print(f"Loss pre training: {classification_loss_pre_training}") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode='forecasting', validate_every=1, test_every=2) - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode='classification', validate_every=1, test_every=2) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="forecasting", + validate_every=1, + test_every=2, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="classification", + validate_every=1, + test_every=2, + ) - _, _, classification_loss_post_training = trainer.validate(data_loaders['train_loader']) + _, _, classification_loss_post_training = trainer.validate( + data_loaders["train_loader"] + ) - print(f'Loss post training: {classification_loss_post_training}') + print(f"Loss post training: {classification_loss_post_training}") assert classification_loss_post_training < classification_loss_pre_training +@pytest.mark.skipif( + sys.platform == "darwin" or sys.platform == "win32", + reason="hangs on Windows and Mac for unknown reason", +) def test_vae_classification_network_converges(): """ Test that Autoencoder and variational auto encoder models for classification networks converge @@ -502,59 +637,79 @@ def test_vae_classification_network_converges(): yy = sample_class * np.cos(sequence / 20.0) + (sample_class - 1) * sequence data.append([xx, yy, sample_id, sample_class]) # Sample data - df = pd.DataFrame(data, columns=['x', 'y', 'ID', 'class']) + df = pd.DataFrame(data, columns=["x", "y", "ID", "class"]) # Hyperparameters batch_size = 2 num_past = 10 num_future = 5 # Prepare the dataloader - data_loaders = dataset.MultiModalDataLoader(df, - batch_size=batch_size, - n_past=num_past, - n_future=num_future, - train_split_ratio=0.333, - validation_split_ratio=0.333, - num_workers=1, - split_by_id=False, - stride=1) - - model_save_path = './model.pt' - - model = MultiModelVAE(input_size=2, - output_size=2, - lstm_hidden_size=32, - num_lstm_layers=2, - num_classes=2, - latent_size=10, - dropout=0.1, - num_classifier_layers=4, - classifier_hidden_size=32, - batch_size=batch_size, - num_future=num_future, - num_past=num_past, - bidirectional=False, - batch_first=True, - reset_state=True) + data_loaders = dataset.MultiModalDataLoader( + df, + batch_size=batch_size, + n_past=num_past, + n_future=num_future, + train_split_ratio=0.333, + validation_split_ratio=0.333, + num_workers=1, + split_by_id=False, + stride=1, + ) + + model_save_path = "./model.pt" + + model = MultiModelVAE( + input_size=2, + output_size=2, + lstm_hidden_size=32, + num_lstm_layers=2, + num_classes=2, + latent_size=10, + dropout=0.1, + num_classifier_layers=4, + classifier_hidden_size=32, + batch_size=batch_size, + num_future=num_future, + num_past=num_past, + bidirectional=False, + batch_first=True, + reset_state=True, + ) # Test resetting the classifier, to make sure this function works model.reset_classifier(classifier_hidden_size=32, num_classifier_layers=4) # Model Trainer # Model types; "ae" or "vae" - trainer = HybridTrainer(model=model, - optimizer_type='Adam', - loss_type='mse') + trainer = HybridTrainer(model=model, optimizer_type="Adam", loss_type="mse") - _, _, classification_loss_pre_training = trainer.validate(data_loaders['train_loader']) + _, _, classification_loss_pre_training = trainer.validate( + data_loaders["train_loader"] + ) - print(f'Loss pre training: {classification_loss_pre_training}') + print(f"Loss pre training: {classification_loss_pre_training}") # Train the model - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="forecasting", validate_every=1, test_every=2) - trainer.fit(data_loaders, model_save_path, epochs=2, training_mode="classification", validate_every=1, test_every=2) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="forecasting", + validate_every=1, + test_every=2, + ) + trainer.fit( + data_loaders, + model_save_path, + epochs=2, + training_mode="classification", + validate_every=1, + test_every=2, + ) - _, _, classification_loss_post_training = trainer.validate(data_loaders['train_loader']) + _, _, classification_loss_post_training = trainer.validate( + data_loaders["train_loader"] + ) - print(f'Loss post training: {classification_loss_post_training}') + print(f"Loss post training: {classification_loss_post_training}") assert classification_loss_post_training < classification_loss_pre_training diff --git a/traja/tests/test_stats.py b/traja/tests/test_stats.py index 84d60141..53890c00 100644 --- a/traja/tests/test_stats.py +++ b/traja/tests/test_stats.py @@ -1,10 +1,11 @@ from traja.stats.brownian import Brownian import numpy as np + def test_brownian_walk_generates_correct_number_of_samples(): length = 1000000 brownian = Brownian(length=length) - assert(len(brownian) == length) + assert len(brownian) == length def test_brownian_motion_with_drift_approximately_sums_to_the_drift(): @@ -58,8 +59,12 @@ def test_brownians_with_different_time_steps_walk_approximately_equally(): drift1 = 0 drift2 = 0 - brownian1 = Brownian(length=length1, mean_value=mean_drift, variance=variance, dt=dt1) - brownian2 = Brownian(length=length2, mean_value=mean_drift, variance=variance, dt=dt2) + brownian1 = Brownian( + length=length1, mean_value=mean_drift, variance=variance, dt=dt1 + ) + brownian2 = Brownian( + length=length2, mean_value=mean_drift, variance=variance, dt=dt2 + ) for i in range(length1): drift1 = brownian1() diff --git a/traja/trajectory.py b/traja/trajectory.py index 26a4d320..6b6c7090 100644 --- a/traja/trajectory.py +++ b/traja/trajectory.py @@ -201,10 +201,10 @@ def expected_sq_displacement( sl = traja.step_lengths(trj) ta = traja.calc_angle(trj) l1 = np.mean(sl) - l2 = np.mean(sl ** 2) + l2 = np.mean(sl**2) c = np.mean(np.cos(ta)) s = np.mean(np.sin(ta)) - s2 = s ** 2 + s2 = s**2 if eqn1: # Eqn 1 @@ -214,9 +214,9 @@ def expected_sq_displacement( ) * np.sin((n + 1) * alpha) esd = ( n * l2 - + 2 * l1 ** 2 * ((c - c ** 2 - s2) * n - c) / ((1 - c) ** 2 + s2) + + 2 * l1**2 * ((c - c**2 - s2) * n - c) / ((1 - c) ** 2 + s2) + 2 - * l1 ** 2 + * l1**2 * ((2 * s2 + (c + s2) ** ((n + 1) / 2)) / ((1 - c) ** 2 + s2) ** 2) * gamma ) @@ -224,7 +224,7 @@ def expected_sq_displacement( else: logger.info("This method is experimental and requires testing.") # Eqn 2 - esd = n * l2 + 2 * l1 ** 2 * c / (1 - c) * (n - (1 - c ** n) / (1 - c)) + esd = n * l2 + 2 * l1**2 * c / (1 - c) * (n - (1 - c**n) / (1 - c)) return esd @@ -373,7 +373,7 @@ def transition_matrix(grid_indices1D: np.ndarray): M = [[0] * n for _ in range(n)] - for (i, j) in zip(grid_indices1D, grid_indices1D[1:]): + for i, j in zip(grid_indices1D, grid_indices1D[1:]): M[i][j] += 1 # Convert to probabilities @@ -458,7 +458,7 @@ def calc_flow_angles(grid_indices: np.ndarray): M = np.empty((bins[1], bins[0]), dtype=np.ndarray) - for (i, j) in zip(grid_indices, grid_indices[1:]): + for i, j in zip(grid_indices, grid_indices[1:]): # Account for fact that grid indices uses 1-base indexing ix = i[0] - 1 iy = i[1] - 1 @@ -930,7 +930,7 @@ def _rediscretize_points( V = (curr_result_y - prev_y) * cos_l - (curr_result_x - prev_x) * sin_l # Compute distance H between (X_{i+1}, Y_{i+1}) and (x_{k-1}, y_{k-1}) - H = U + np.sqrt(abs(R ** 2 - V ** 2)) + H = U + np.sqrt(abs(R**2 - V**2)) XIp1 = H * cos_l + prev_x YIp1 = H * sin_l + prev_y @@ -1073,7 +1073,7 @@ def calc_derivatives(trj: TrajaDataFrame): # get cumulative seconds if is_datetime64_any_dtype(trj[time_col]): displacement_time = ( - trj[time_col].astype(int).div(10 ** 9).diff().fillna(0).cumsum() + trj[time_col].astype(int).div(10**9).diff().fillna(0).cumsum() ) else: try: From b405cfcc68f2ed81554cc242329ea2f9282e8607 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:50:06 +0100 Subject: [PATCH 17/21] Apply isort --- traja/__init__.py | 8 ++++---- traja/contrib/rdp.py | 2 +- traja/dataset/__init__.py | 2 +- traja/dataset/pedestrian.py | 7 ++++--- traja/frame.py | 2 +- traja/models/__init__.py | 3 ++- traja/parsers.py | 3 ++- traja/plotting.py | 15 ++++++--------- traja/stats/brownian.py | 2 +- traja/tests/test_dataset.py | 1 + traja/tests/test_models.py | 9 ++++----- traja/tests/test_stats.py | 3 ++- traja/tests/test_trajadataframe.py | 2 +- traja/trajectory.py | 8 +++----- 14 files changed, 33 insertions(+), 34 deletions(-) diff --git a/traja/__init__.py b/traja/__init__.py index 90fa0d51..344cf2c4 100644 --- a/traja/__init__.py +++ b/traja/__init__.py @@ -1,10 +1,10 @@ import logging -from traja import dataset -from traja import models +from traja import dataset, models + from .accessor import TrajaAccessor -from .frame import TrajaDataFrame, TrajaCollection -from .parsers import read_file, from_df +from .frame import TrajaCollection, TrajaDataFrame +from .parsers import from_df, read_file from .plotting import * from .trajectory import * diff --git a/traja/contrib/rdp.py b/traja/contrib/rdp.py index 89a99550..a787b877 100644 --- a/traja/contrib/rdp.py +++ b/traja/contrib/rdp.py @@ -21,7 +21,7 @@ """ from functools import partial -from typing import Union, Callable +from typing import Callable, Union import numpy as np diff --git a/traja/dataset/__init__.py b/traja/dataset/__init__.py index 0feb17b9..85e6bc3b 100644 --- a/traja/dataset/__init__.py +++ b/traja/dataset/__init__.py @@ -1,3 +1,3 @@ from . import example -from .dataset import TimeSeriesDataset, MultiModalDataLoader +from .dataset import MultiModalDataLoader, TimeSeriesDataset from .pedestrian import load_ped_data, ped_datasets diff --git a/traja/dataset/pedestrian.py b/traja/dataset/pedestrian.py index 89ad8f26..5a62a92f 100644 --- a/traja/dataset/pedestrian.py +++ b/traja/dataset/pedestrian.py @@ -1,11 +1,12 @@ -import subprocess import glob import os +import subprocess from typing import List + import pandas as pd -from traja.dataset import dataset -import traja +import traja +from traja.dataset import dataset """Convenience module for downloading pedestrian-related datasets.""" diff --git a/traja/frame.py b/traja/frame.py index f210d09d..bf0b7126 100644 --- a/traja/frame.py +++ b/traja/frame.py @@ -1,6 +1,6 @@ import logging -from typing import Optional, Union, Tuple import warnings +from typing import Optional, Tuple, Union import numpy as np import pandas as pd diff --git a/traja/models/__init__.py b/traja/models/__init__.py index 65c12776..3a8b9151 100644 --- a/traja/models/__init__.py +++ b/traja/models/__init__.py @@ -2,6 +2,7 @@ from traja.models.generative_models.vaegan import MultiModelVAEGAN from traja.models.predictive_models.ae import MultiModelAE from traja.models.predictive_models.lstm import LSTM + from .inference import * from .train import HybridTrainer -from .utils import TimeDistributed, read_hyperparameters, save, load +from .utils import TimeDistributed, load, read_hyperparameters, save diff --git a/traja/parsers.py b/traja/parsers.py index e5414ec0..dd399cfc 100644 --- a/traja/parsers.py +++ b/traja/parsers.py @@ -2,7 +2,8 @@ import numpy as np import pandas as pd -from pandas.core.dtypes.common import is_datetime64_any_dtype, is_timedelta64_dtype +from pandas.core.dtypes.common import (is_datetime64_any_dtype, + is_timedelta64_dtype) from traja import TrajaDataFrame diff --git a/traja/plotting.py b/traja/plotting.py index f7b4ef80..f9feffbd 100644 --- a/traja/plotting.py +++ b/traja/plotting.py @@ -1,27 +1,24 @@ import logging +import os from collections import OrderedDict from datetime import timedelta -import os -from typing import Union, Optional, Tuple, List +from typing import List, Optional, Tuple, Union import matplotlib import matplotlib.pyplot as plt import numpy as np import pandas as pd import torch - from matplotlib import dates as md from matplotlib.axes import Axes from matplotlib.collections import PathCollection from matplotlib.figure import Figure -from pandas.core.dtypes.common import ( - is_datetime64_any_dtype, - is_timedelta64_dtype, -) +from pandas.core.dtypes.common import (is_datetime64_any_dtype, + is_timedelta64_dtype) import traja -from traja.frame import TrajaDataFrame from traja.core import is_datetime_or_timedelta_dtype +from traja.frame import TrajaDataFrame from traja.trajectory import coords_to_flow __all__ = [ @@ -1320,9 +1317,9 @@ def plot_transition_graph( """ try: + import graphviz import networkx as nx import pydot - import graphviz except ImportError as e: raise ImportError(f"{e} - please install it with pip") diff --git a/traja/stats/brownian.py b/traja/stats/brownian.py index 79b43952..fdb2a77a 100644 --- a/traja/stats/brownian.py +++ b/traja/stats/brownian.py @@ -1,5 +1,5 @@ -from scipy.stats import norm import numpy as np +from scipy.stats import norm class Brownian: diff --git a/traja/tests/test_dataset.py b/traja/tests/test_dataset.py index 1081b44c..3d60471a 100644 --- a/traja/tests/test_dataset.py +++ b/traja/tests/test_dataset.py @@ -1,4 +1,5 @@ import sys + import pandas as pd import pytest diff --git a/traja/tests/test_models.py b/traja/tests/test_models.py index 2ba023e3..6544287f 100644 --- a/traja/tests/test_models.py +++ b/traja/tests/test_models.py @@ -1,15 +1,14 @@ +import sys + import numpy as np import pandas as pd +import pytest import traja from traja.dataset import dataset from traja.dataset.example import jaguar -from traja.models import LSTM -from traja.models import MultiModelAE -from traja.models import MultiModelVAE +from traja.models import LSTM, MultiModelAE, MultiModelVAE from traja.models.train import HybridTrainer -import sys -import pytest @pytest.mark.skipif( diff --git a/traja/tests/test_stats.py b/traja/tests/test_stats.py index 53890c00..f153c062 100644 --- a/traja/tests/test_stats.py +++ b/traja/tests/test_stats.py @@ -1,6 +1,7 @@ -from traja.stats.brownian import Brownian import numpy as np +from traja.stats.brownian import Brownian + def test_brownian_walk_generates_correct_number_of_samples(): length = 1000000 diff --git a/traja/tests/test_trajadataframe.py b/traja/tests/test_trajadataframe.py index 41949a1c..1897a433 100644 --- a/traja/tests/test_trajadataframe.py +++ b/traja/tests/test_trajadataframe.py @@ -6,7 +6,7 @@ from pandas import DataFrame import traja -from traja import TrajaDataFrame, read_file, TrajaCollection +from traja import TrajaCollection, TrajaDataFrame, read_file class TestDataFrame: diff --git a/traja/trajectory.py b/traja/trajectory.py index 6b6c7090..85b1a08c 100644 --- a/traja/trajectory.py +++ b/traja/trajectory.py @@ -1,14 +1,12 @@ import logging import math from collections import OrderedDict -from typing import Callable, Optional, Union, Tuple +from typing import Callable, Optional, Tuple, Union import numpy as np import pandas as pd -from pandas.core.dtypes.common import ( - is_datetime64_any_dtype, - is_timedelta64_dtype, -) +from pandas.core.dtypes.common import (is_datetime64_any_dtype, + is_timedelta64_dtype) from scipy import signal from scipy.spatial.distance import directed_hausdorff, euclidean From ab28790b99bcb4407997a5262c136054e8b78d89 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 20:50:49 +0100 Subject: [PATCH 18/21] Add formatter and isort to requirements --- requirements/extra.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements/extra.txt b/requirements/extra.txt index 13d86760..87ce5253 100644 --- a/requirements/extra.txt +++ b/requirements/extra.txt @@ -5,4 +5,6 @@ h5py ipython pre-commit h5py -numba>=0.50.1 \ No newline at end of file +numba>=0.50.1 +black +isort \ No newline at end of file From 4eb8bae42830e2a8109b5a0c4c0644162acd5ce4 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 22:08:48 +0100 Subject: [PATCH 19/21] Add load pedestrian dataset --- .gitignore | 1 + traja/__init__.py | 2 +- traja/tests/test_dataset.py | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 679af2c0..841b7464 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,4 @@ docs/source/reference # Model parameter files *.pt .python-version +datasets/ \ No newline at end of file diff --git a/traja/__init__.py b/traja/__init__.py index 344cf2c4..306488a6 100644 --- a/traja/__init__.py +++ b/traja/__init__.py @@ -9,7 +9,7 @@ from .trajectory import * __author__ = "justinshenk" -__version__ = "22.0.0" +__version__ = "23.0.0" logging.basicConfig(level=logging.INFO) diff --git a/traja/tests/test_dataset.py b/traja/tests/test_dataset.py index 3d60471a..f31d530d 100644 --- a/traja/tests/test_dataset.py +++ b/traja/tests/test_dataset.py @@ -3,7 +3,7 @@ import pandas as pd import pytest -from traja.dataset import dataset +from traja.dataset import dataset, load_ped_data @pytest.mark.skipif( @@ -615,3 +615,9 @@ def test_sequential_data_loader_indices_are_sequential(): assert ( id == current_id ), "IDs in sequential test loader should increase monotonically!" + + +# Load the pedestrian datasets +def test_ped_datasets(): + dfs = load_ped_data() + assert len(dfs) == 3 From 7e2d60a955048db4cda141701788f2f426375a88 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 22:19:22 +0100 Subject: [PATCH 20/21] Fix Windows wget tests (not install on GitHub actions image) --- setup.cfg | 2 +- traja/tests/test_dataset.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 674af40a..03faf68a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.0 +current_version = 23.0.0 [yapf] column_limit = 120 diff --git a/traja/tests/test_dataset.py b/traja/tests/test_dataset.py index f31d530d..c70c5b98 100644 --- a/traja/tests/test_dataset.py +++ b/traja/tests/test_dataset.py @@ -618,6 +618,10 @@ def test_sequential_data_loader_indices_are_sequential(): # Load the pedestrian datasets +@pytest.mark.skipif( + sys.platform == "win32", + reason="GitHub actions images don't have wget installed.", +) def test_ped_datasets(): dfs = load_ped_data() assert len(dfs) == 3 From 0571684c3eb1e501eab431d9b48338a603f524f2 Mon Sep 17 00:00:00 2001 From: Wolf Byttner Date: Sat, 6 Apr 2024 22:20:59 +0100 Subject: [PATCH 21/21] Name Miniconda jobs with Platform + Ptyhon version --- .github/workflows/tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index b5651f88..c5e0f157 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -9,7 +9,7 @@ on: jobs: miniconda: - name: Miniconda ${{ matrix.os }} + name: Miniconda ${{ matrix.os }} - Python ${{ matrix.python-version }} runs-on: ${{ matrix.os }} strategy: matrix: @@ -17,7 +17,7 @@ jobs: python-version: [ "3.8", "3.12" ] steps: - uses: actions/checkout@v2 - - name: Set up Miniconda ${{ matrix.python-version }} + - name: Set up Miniconda (Python ${{ matrix.python-version }}) uses: conda-incubator/setup-miniconda@v2 with: activate-environment: test