Skip to content

Commit

Permalink
chore(release): v1.1.0 (#80)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicrie authored Aug 31, 2023
2 parents 58c2f09 + 2482110 commit f576cb1
Show file tree
Hide file tree
Showing 23 changed files with 2,531 additions and 437 deletions.
34 changes: 34 additions & 0 deletions docs/_autosummary/xeofs.models.OPA.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
xeofs.models.OPA
================

.. currentmodule:: xeofs.models

.. autoclass:: OPA
:members:
:show-inheritance:
:inherited-members:


.. automethod:: __init__


.. rubric:: Methods

.. autosummary::

~OPA.__init__
~OPA.components
~OPA.compute
~OPA.decorrelation_time
~OPA.filter_patterns
~OPA.fit
~OPA.get_params
~OPA.inverse_transform
~OPA.scores
~OPA.transform






1 change: 1 addition & 0 deletions docs/api_core_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Core methods
:recursive:

xeofs.models.EOF
xeofs.models.OPA
xeofs.models.MCA
11 changes: 11 additions & 0 deletions docs/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ The supported models in ``xeofs`` currently include:
Uncovers co-varying patterns between two sets of data.


.. grid:: 2

.. grid-item-card:: Optimal Persistence Analysis (OPA)
:link: api_core_methods
:link-type: doc


Identifies the optimal persistence patterns (OPP) with the largest decorrelation time.



Enhanced Interpretability
---------------------------

Expand Down
69 changes: 0 additions & 69 deletions tests/models/test_cross_decomposer.py

This file was deleted.

98 changes: 85 additions & 13 deletions tests/models/test_decomposer.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,97 @@ def test_init(decomposer):
assert decomposer.solver_kwargs["random_state"] == 42


def test_fit(decomposer, mock_data_array):
def test_fit_full(mock_data_array):
decomposer = Decomposer(n_modes=2, solver="full")
decomposer.fit(mock_data_array)
assert "scores_" in decomposer.__dict__
assert "singular_values_" in decomposer.__dict__
assert "components_" in decomposer.__dict__
assert "U_" in decomposer.__dict__
assert "s_" in decomposer.__dict__
assert "V_" in decomposer.__dict__

# Check that indeed 2 modes are returned
assert decomposer.U_.shape[1] == 2
assert decomposer.s_.shape[0] == 2
assert decomposer.V_.shape[1] == 2

def test_fit_dask(mock_dask_data_array):

def test_fit_full_matrices(mock_data_array):
decomposer = Decomposer(n_modes=2, solver="full", full_matrices=False)
decomposer.fit(mock_data_array)
assert "U_" in decomposer.__dict__
assert "s_" in decomposer.__dict__
assert "V_" in decomposer.__dict__

# Check that indeed 2 modes are returned
assert decomposer.U_.shape[1] == 2
assert decomposer.s_.shape[0] == 2
assert decomposer.V_.shape[1] == 2


def test_fit_randomized(mock_data_array):
decomposer = Decomposer(n_modes=2, solver="randomized", random_state=42)
decomposer.fit(mock_data_array)
assert "U_" in decomposer.__dict__
assert "s_" in decomposer.__dict__
assert "V_" in decomposer.__dict__

# Check that indeed 2 modes are returned
assert decomposer.U_.shape[1] == 2
assert decomposer.s_.shape[0] == 2
assert decomposer.V_.shape[1] == 2


def test_fit_dask_full(mock_dask_data_array):
# The Dask SVD solver has no parameter 'random_state' but 'seed' instead,
# so let's create a new decomposer for this case
decomposer = Decomposer(n_modes=2, seed=42)
decomposer = Decomposer(n_modes=2, solver="full")
decomposer.fit(mock_dask_data_array)
assert "scores_" in decomposer.__dict__
assert "singular_values_" in decomposer.__dict__
assert "components_" in decomposer.__dict__
assert "U_" in decomposer.__dict__
assert "s_" in decomposer.__dict__
assert "V_" in decomposer.__dict__

# Check if the Dask SVD solver has been used
assert isinstance(decomposer.U_.data, DaskArray)
assert isinstance(decomposer.s_.data, DaskArray)
assert isinstance(decomposer.V_.data, DaskArray)

# Check that indeed 2 modes are returned
assert decomposer.U_.shape[1] == 2
assert decomposer.s_.shape[0] == 2
assert decomposer.V_.shape[1] == 2


def test_fit_dask_randomized(mock_dask_data_array):
# The Dask SVD solver has no parameter 'random_state' but 'seed' instead,
# so let's create a new decomposer for this case
decomposer = Decomposer(n_modes=2, solver="randomized", seed=42)
decomposer.fit(mock_dask_data_array)
assert "U_" in decomposer.__dict__
assert "s_" in decomposer.__dict__
assert "V_" in decomposer.__dict__

# Check if the Dask SVD solver has been used
assert isinstance(decomposer.U_.data, DaskArray)
assert isinstance(decomposer.s_.data, DaskArray)
assert isinstance(decomposer.V_.data, DaskArray)

# Check that indeed 2 modes are returned
assert decomposer.U_.shape[1] == 2
assert decomposer.s_.shape[0] == 2
assert decomposer.V_.shape[1] == 2


def test_fit_complex(decomposer, mock_complex_data_array):
def test_fit_complex(mock_complex_data_array):
decomposer = Decomposer(n_modes=2, solver="randomized", random_state=42)
decomposer.fit(mock_complex_data_array)
assert "scores_" in decomposer.__dict__
assert "singular_values_" in decomposer.__dict__
assert "components_" in decomposer.__dict__
assert "U_" in decomposer.__dict__
assert "s_" in decomposer.__dict__
assert "V_" in decomposer.__dict__

# Check that indeed 2 modes are returned
assert decomposer.U_.shape[1] == 2
assert decomposer.s_.shape[0] == 2
assert decomposer.V_.shape[1] == 2

# Check that U and V are complex
assert np.iscomplexobj(decomposer.U_.data)
assert np.iscomplexobj(decomposer.V_.data)
4 changes: 3 additions & 1 deletion tests/models/test_eof.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def test_init():
"standardize": True,
"use_coslat": True,
"use_weights": False,
"solver": "auto",
}

# Assert preprocessor has been initialized
Expand Down Expand Up @@ -258,6 +259,7 @@ def test_get_params():
"standardize": True,
"use_coslat": True,
"use_weights": False,
"solver": "auto",
}


Expand All @@ -273,7 +275,7 @@ def test_transform(dim, mock_data_array):
"""Test projecting new unseen data onto the components (EOFs/eigenvectors)"""

# Create a xarray DataArray with random data
model = EOF(n_modes=5, solver_kwargs={"random_state": 0})
model = EOF(n_modes=5, solver="full")
model.fit(mock_data_array, dim)
scores = model.scores()

Expand Down
Loading

0 comments on commit f576cb1

Please sign in to comment.