From 9eba56d091cd6bc81b5c6ccc83478aabf7ed785a Mon Sep 17 00:00:00 2001 From: Nick Johnson <24689722+ntjohnson1@users.noreply.github.com> Date: Sat, 14 Dec 2024 09:08:47 -0500 Subject: [PATCH 1/4] Internal: Try new link checker --- .github/workflows/markdown-check.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/markdown-check.yml b/.github/workflows/markdown-check.yml index 6e0dcbe3..2014353d 100644 --- a/.github/workflows/markdown-check.yml +++ b/.github/workflows/markdown-check.yml @@ -7,8 +7,14 @@ on: branches: [ "main" ] jobs: - markdown-link-check: + check-links: + name: runner / linkspector runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: gaurav-nelson/github-action-markdown-link-check@v1 + - uses: actions/checkout@v4 + - name: Run linkspector + uses: umbrelladocs/action-linkspector@v1 + with: + github_token: ${{ secrets.github_token }} + reporter: github-pr-review + fail_on_error: true From fd1bf9128c8c6630e56a29c3d1d60ebb6c8776d4 Mon Sep 17 00:00:00 2001 From: Nick Johnson <24689722+ntjohnson1@users.noreply.github.com> Date: Sat, 14 Dec 2024 09:40:28 -0500 Subject: [PATCH 2/4] Internal: Add codespell and fix typos. --- .pre-commit-config.yaml | 4 ++++ CHANGELOG.md | 4 ++-- CONTRIBUTING.md | 16 +++++++++++----- README.md | 2 +- docs/source/tutorial/algorithm_cp_als.ipynb | 4 ++-- docs/source/tutorial/algorithm_gcp_opt.ipynb | 2 +- docs/source/tutorial/algorithm_hosvd.ipynb | 2 +- docs/source/tutorial/class_sptensor.ipynb | 2 +- docs/source/tutorial/class_sumtensor.ipynb | 2 +- docs/source/tutorial/class_tenmat.ipynb | 2 +- docs/source/tutorial/class_tensor.ipynb | 4 ++-- docs/source/tutorial/class_ttensor.ipynb | 2 +- profiling/algorithms_profiling.ipynb | 8 ++++---- pyproject.toml | 20 ++++++++++++++++++++ pyttb/cp_als.py | 2 +- pyttb/cp_apr.py | 20 ++++++++++---------- pyttb/gcp/optimizers.py | 2 +- pyttb/hosvd.py | 2 +- pyttb/ktensor.py | 6 +++--- pyttb/pyttb_utils.py | 6 +++--- pyttb/sptenmat.py | 2 +- pyttb/sptensor.py | 8 ++++---- pyttb/tensor.py | 10 +++++----- tests/gcp/test_fg_est.py | 2 +- tests/test_cp_als.py | 2 +- tests/test_cp_apr.py | 2 +- tests/test_ktensor.py | 6 +++--- tests/test_package.py | 11 +++++++++++ tests/test_sptensor.py | 6 +++--- tests/test_tensor.py | 2 +- 30 files changed, 102 insertions(+), 61 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bdc356f4..a53b97a9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,3 +13,7 @@ repos: --extra-keys=metadata.language_info metadata.vscode metadata.kernelspec cell.metadata.vscode, --drop-empty-cells ] + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 317f9849..12dfcfe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ - Aligning comparison operator output for data classes (https://github.com/sandialabs/pyttb/pull/331) - Improved: - Getting starting documentation (https://github.com/sandialabs/pyttb/pull/324) - - Development enviroment (https://github.com/sandialabs/pyttb/pull/329, https://github.com/sandialabs/pyttb/pull/330) + - Development environment (https://github.com/sandialabs/pyttb/pull/329, https://github.com/sandialabs/pyttb/pull/330) - Documentation (https://github.com/sandialabs/pyttb/pull/328, https://github.com/sandialabs/pyttb/pull/334) # v1.8.0 (2024-10-23) @@ -84,7 +84,7 @@ - Addresses ambiguity of -0 by using `exclude_dims` (`numpy.ndarray`) parameter - `ktensor.ttv`, `sptensor.ttv`, `tensor.ttv`, `ttensor.ttv` - Use `exlude_dims` parameter instead of `-dims` - - Explicit nameing of dimensions to exclude + - Explicit naming of dimensions to exclude - `tensor.ttsv` - Use `skip_dim` (`int`) parameter instead of `-dims` - Exclude all dimensions up to and including `skip_dim` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4aaf4c8e..9250cd63 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,12 +35,12 @@ current or filing a new [issue](https://github.com/sandialabs/pyttb/issues). ``` git checkout -b my-new-feature-branch ``` -1. Formatters and linting +1. Formatters and linting (These are checked in the full test suite as well) 1. Run autoformatters and linting from root of project (they will change your code) - ```commandline - ruff check . --fix - ruff format - ``` + ```commandline + ruff check . --fix + ruff format + ``` 1. Ruff's `--fix` won't necessarily address everything and may point out issues that need manual attention 1. [We](./.pre-commit-config.yaml) optionally support [pre-commit hooks](https://pre-commit.com/) for this 1. Alternatively, you can run `pre-commit run --all-files` from the command line if you don't want to install the hooks. @@ -48,6 +48,12 @@ current or filing a new [issue](https://github.com/sandialabs/pyttb/issues). ```commandline mypy pyttb/ ``` + 1. Not included in our pre-commit hooks because of slow runtime. + 1. Check spelling + ```commandline + codespell + ``` + 1. This is also included in the optional pre-commit hooks. 1. Run tests (at desired fidelity) 1. Just doctests (enabled by default) diff --git a/README.md b/README.md index 3382d6f1..9551b025 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ low-rank tensor decompositions: [`cp_apr`](https://pyttb.readthedocs.io/en/stable/cpapr.html "CP decomposition via Alternating Poisson Regression"), [`gcp_opt`](https://pyttb.readthedocs.io/en/stable/gcpopt.html "Generalized CP decomposition"), [`hosvd`](https://pyttb.readthedocs.io/en/stable/hosvd.html "Tucker decomposition via Higher Order Singular Value Decomposition"), -[`tucker_als`](https://pyttb.readthedocs.io/en/stable/tuckerals.html "Tucker decompostion via Alternating Least Squares") +[`tucker_als`](https://pyttb.readthedocs.io/en/stable/tuckerals.html "Tucker decomposition via Alternating Least Squares") ## Quick Start diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index 4ccc5975..a74c9436 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -122,7 +122,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Increase the maximium number of iterations\n", + "## Increase the maximum number of iterations\n", "Note that the previous run kicked out at only 10 iterations, before reaching the specified convegence tolerance. Let's increase the maximum number of iterations and try again, using the same initial guess." ] }, @@ -337,7 +337,7 @@ "source": [ "## Recommendations\n", "* Run multiple times with different guesses and select the solution with the best fit.\n", - "* Try different ranks and choose the solution that is the best descriptor for your data based on the combination of the fit and the interpretaton of the factors, e.g., by visualizing the results." + "* Try different ranks and choose the solution that is the best descriptor for your data based on the combination of the fit and the interpretation of the factors, e.g., by visualizing the results." ] } ], diff --git a/docs/source/tutorial/algorithm_gcp_opt.ipynb b/docs/source/tutorial/algorithm_gcp_opt.ipynb index ee5b5d04..78488d16 100644 --- a/docs/source/tutorial/algorithm_gcp_opt.ipynb +++ b/docs/source/tutorial/algorithm_gcp_opt.ipynb @@ -19,7 +19,7 @@ "tags": [] }, "source": [ - "This document outlines usage and examples for the generalized CP (GCP) tensor decomposition implmented in `pyttb.gcp_opt`. GCP allows alternate objective functions besides sum of squared errors, which is the standard for CP. The code support both dense and sparse input tensors, but the sparse input tensors require randomized optimization methods.\n", + "This document outlines usage and examples for the generalized CP (GCP) tensor decomposition implemented in `pyttb.gcp_opt`. GCP allows alternate objective functions besides sum of squared errors, which is the standard for CP. The code support both dense and sparse input tensors, but the sparse input tensors require randomized optimization methods.\n", "\n", "GCP is described in greater detail in the manuscripts:\n", "* D. Hong, T. G. Kolda, J. A. Duersch, Generalized Canonical Polyadic Tensor Decomposition, SIAM Review, 62:133-163, 2020, https://doi.org/10.1137/18M1203626\n", diff --git a/docs/source/tutorial/algorithm_hosvd.ipynb b/docs/source/tutorial/algorithm_hosvd.ipynb index c17c790d..e8973c0d 100644 --- a/docs/source/tutorial/algorithm_hosvd.ipynb +++ b/docs/source/tutorial/algorithm_hosvd.ipynb @@ -94,7 +94,7 @@ "metadata": {}, "source": [ "## Generate a core with different accuracies for different shapes\n", - "We will create a core `tensor` that has is nearly block diagonal. The blocks are expontentially decreasing in norm, with the idea that we can pick off one block at a time as we increate the prescribed accuracy of the HOSVD. To do this, we define and use a function `tenrandblk()`." + "We will create a core `tensor` that has is nearly block diagonal. The blocks are expontentially decreasing in norm, with the idea that we can pick off one block at a time as we increase the prescribed accuracy of the HOSVD. To do this, we define and use a function `tenrandblk()`." ] }, { diff --git a/docs/source/tutorial/class_sptensor.ipynb b/docs/source/tutorial/class_sptensor.ipynb index bd2b072a..75c10ce6 100644 --- a/docs/source/tutorial/class_sptensor.ipynb +++ b/docs/source/tutorial/class_sptensor.ipynb @@ -17,7 +17,7 @@ "metadata": {}, "source": [ "## Creating a `sptensor`\n", - "The `sptensor` class stores the data in coordinate format. A sparse `sptensor` can be created by passing in a list of subscripts and values. For example, here we pass in three subscripts and a scalar value. The resuling sparse `sptensor` has three nonzero entries, and the `shape` is the size of the largest subscript in each dimension." + "The `sptensor` class stores the data in coordinate format. A sparse `sptensor` can be created by passing in a list of subscripts and values. For example, here we pass in three subscripts and a scalar value. The resulting sparse `sptensor` has three nonzero entries, and the `shape` is the size of the largest subscript in each dimension." ] }, { diff --git a/docs/source/tutorial/class_sumtensor.ipynb b/docs/source/tutorial/class_sumtensor.ipynb index 8230044f..4ca273ae 100644 --- a/docs/source/tutorial/class_sumtensor.ipynb +++ b/docs/source/tutorial/class_sumtensor.ipynb @@ -54,7 +54,7 @@ "metadata": {}, "source": [ "## Creating sumtensors\n", - "A sumtensor `T` can only be delared as a sum of same-shaped tensors T1, T2,...,TN. The summand tensors are stored internally, which define the \"parts\" of the `sumtensor`. The parts of a `sumtensor` can be (dense) tensors (`tensor`), sparse tensors (` sptensor`), Kruskal tensors (`ktensor`), or Tucker tensors (`ttensor`). An example of the use of the sumtensor constructor follows." + "A sumtensor `T` can only be declared as a sum of same-shaped tensors T1, T2,...,TN. The summand tensors are stored internally, which define the \"parts\" of the `sumtensor`. The parts of a `sumtensor` can be (dense) tensors (`tensor`), sparse tensors (` sptensor`), Kruskal tensors (`ktensor`), or Tucker tensors (`ttensor`). An example of the use of the sumtensor constructor follows." ] }, { diff --git a/docs/source/tutorial/class_tenmat.ipynb b/docs/source/tutorial/class_tenmat.ipynb index 034c0ce9..4b5e9b22 100644 --- a/docs/source/tutorial/class_tenmat.ipynb +++ b/docs/source/tutorial/class_tenmat.ipynb @@ -16,7 +16,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We show how to convert a `tensor` to a 2D numpy array stored with extra information so that it can be converted back to a `tensor`. Converting to a 2D numpy array requies an ordered mapping of the `tensor` indices to the rows and the columns of the 2D numpy array." + "We show how to convert a `tensor` to a 2D numpy array stored with extra information so that it can be converted back to a `tensor`. Converting to a 2D numpy array requires an ordered mapping of the `tensor` indices to the rows and the columns of the 2D numpy array." ] }, { diff --git a/docs/source/tutorial/class_tensor.ipynb b/docs/source/tutorial/class_tensor.ipynb index bc1b1fb6..b8db6cdf 100644 --- a/docs/source/tutorial/class_tensor.ipynb +++ b/docs/source/tutorial/class_tensor.ipynb @@ -107,7 +107,7 @@ "metadata": {}, "source": [ "## Specifying trailing singleton dimensions in a `tensor`\n", - "Likewise, trailing singleton dimensions must be explictly specified." + "Likewise, trailing singleton dimensions must be explicitly specified." ] }, { @@ -136,7 +136,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## The constitutent parts of a `tensor`" + "## The constituent parts of a `tensor`" ] }, { diff --git a/docs/source/tutorial/class_ttensor.ipynb b/docs/source/tutorial/class_ttensor.ipynb index 0b00f4db..86c25055 100644 --- a/docs/source/tutorial/class_ttensor.ipynb +++ b/docs/source/tutorial/class_ttensor.ipynb @@ -630,7 +630,7 @@ "metadata": {}, "source": [ "### Compare visualizations\n", - "We can compare the results of reconstruction. There is no degredation in doing only a partial reconstruction. Downsampling is obviously lower resolution, but the same result as first doing the full reconstruction and then downsampling." + "We can compare the results of reconstruction. There is no degradation in doing only a partial reconstruction. Downsampling is obviously lower resolution, but the same result as first doing the full reconstruction and then downsampling." ] }, { diff --git a/profiling/algorithms_profiling.ipynb b/profiling/algorithms_profiling.ipynb index 18e34179..9e955727 100644 --- a/profiling/algorithms_profiling.ipynb +++ b/profiling/algorithms_profiling.ipynb @@ -90,7 +90,7 @@ " label:\n", " The user-supplied label to distinguish a test run.\n", " params:\n", - " Paramters passed to the algorithm function.\n", + " Parameters passed to the algorithm function.\n", " 'rank' may be given to the CP algorithms; 'tol' and 'verbosity' to hosvd.\n", " \"\"\"\n", "\n", @@ -108,7 +108,7 @@ " # stop collecting data, and send data to Stats object and sort\n", " profiler.disable()\n", "\n", - " # save profiling ouput to sub-directory specific to the function being tested.\n", + " # save profiling output to sub-directory specific to the function being tested.\n", " output_directory = f\"./pstats_files/{algorithm_name}\"\n", " if not os.path.exists(output_directory):\n", " os.makedirs(output_directory) # create directory if it doesn't exist\n", @@ -155,7 +155,7 @@ " label:\n", " The user-supplied label to distinguish a test run. This will be used in the output file name.\n", " params:\n", - " Paramters passed to the algorithm function.\n", + " Parameters passed to the algorithm function.\n", " 'rank' may be given to the CP algorithms; 'tol' and 'verbosity' to hosvd.\n", " \"\"\"\n", "\n", @@ -410,7 +410,7 @@ "source": [ "### Generating all algorithms' profiling images\n", " \n", - "The cell bellow will generate all profiling images for all algorithms in `./gprof2dot_images/`" + "The cell below will generate all profiling images for all algorithms in `./gprof2dot_images/`" ] }, { diff --git a/pyproject.toml b/pyproject.toml index bf5eb0b5..2d0f1c55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ dev = [ # Also in pre-commit "ruff>=0.7,<0.8", "pre-commit>=4.0,<5.0", + "codespell>=2.3.0,<2.4.0" ] doc = [ "sphinx >= 4.0", @@ -120,3 +121,22 @@ addopts = "--doctest-modules pyttb" filterwarnings = [ "ignore:.*deprecated.*:" ] + +[tool.codespell] +skip = [ + # Built documentation + "./docs/build", + "./docs/jupyter_execute", + # Project build artifacts + "./build" +] +count = true +ignore-words-list = [ + # Conventions carried from MATLAB ttb (consider changing) + "ans", + "siz", + # Tensor/repo Nomenclature + "COO", + "nd", + "als", +] \ No newline at end of file diff --git a/pyttb/cp_als.py b/pyttb/cp_als.py index 68842228..94616547 100644 --- a/pyttb/cp_als.py +++ b/pyttb/cp_als.py @@ -76,7 +76,7 @@ def cp_als( # noqa: PLR0912,PLR0913,PLR0915 Example ------- - Random initialization causes slight pertubation in intermediate results. + Random initialization causes slight perturbation in intermediate results. `...` is our place holder for these numeric values. Example using default values ("random" initialization): diff --git a/pyttb/cp_apr.py b/pyttb/cp_apr.py index 6ae00b62..d87454ee 100644 --- a/pyttb/cp_apr.py +++ b/pyttb/cp_apr.py @@ -104,7 +104,7 @@ def cp_apr( # noqa: PLR0913 assert init.ndims == N, "Initial guess does not have the right number of modes" assert ( init.ncomponents == rank - ), "Initial guess does not have the right number of componenets" + ), "Initial guess does not have the right number of components" for n in range(N): if init.shape[n] != input_tensor.shape[n]: assert False, f"Mode {n} of the initial guess is the wrong size" @@ -256,7 +256,7 @@ def tt_cp_apr_mu( # noqa: PLR0912,PLR0913,PLR0915 M.normalize(normtype=1) Phi = [] # np.zeros((N,))#cell(N,1) for n in range(N): - # TODO prepopulation Phi instead of appen should be faster + # TODO prepopulation Phi instead of append should be faster Phi.append(np.zeros(M.factor_matrices[n].shape)) kktModeViolations = np.zeros((N,)) @@ -488,7 +488,7 @@ def tt_cp_apr_pdnr( # noqa: PLR0912,PLR0913,PLR0915 if isinstance(input_tensor, ttb.sptensor) and isSparse and precompinds: # Precompute sparse index sets for all the row subproblems. - # Takes more memory but can cut exectuion time significantly in some cases. + # Takes more memory but can cut execution time significantly in some cases. if printitn > 0: print("\tPrecomuting sparse index sets...") sparseIx = [] @@ -847,7 +847,7 @@ def tt_cp_apr_pqnr( # noqa: PLR0912,PLR0913,PLR0915 if isinstance(input_tensor, ttb.sptensor) and precompinds: # Precompute sparse index sets for all the row subproblems. - # Takes more memory but can cut exectuion time significantly in some cases. + # Takes more memory but can cut execution time significantly in some cases. if printitn > 0: print("\tPrecomuting sparse index sets...") sparseIx = [] @@ -989,12 +989,12 @@ def tt_cp_apr_pqnr( # noqa: PLR0912,PLR0913,PLR0915 delg[:, lbfgsPos] = tmp_delg rho[lbfgsPos] = tmp_rho else: - # Rho is required to be postive; if not, then skip the L-BFGS + # Rho is required to be positive; if not, then skip the L-BFGS # update pair. The recommended safeguard for full BFGS is # Powell damping, but not clear how to damp in 2-loop L-BFGS if dispLineWarn: warnings.warn( - "WARNING: skipping L-BFGS update, rho whould be " + "WARNING: skipping L-BFGS update, rho would be " f"1 / {tmp_delm * tmp_delg}" ) # Roll back lbfgsPos since it will increment later. @@ -1384,7 +1384,7 @@ def tt_linesearch_prowsubprob( # noqa: PLR0913 max_steps: maximum number of steps to try (suggest 10) suff_decr: - sufficent decrease for convergence (suggest 1.0e-4) + sufficient decrease for convergence (suggest 1.0e-4) isSparse: sparsity flag for computing the objective data_row: @@ -1414,7 +1414,7 @@ def tt_linesearch_prowsubprob( # noqa: PLR0913 stepSize = step_len - # Evalute the current objective value + # Evaluate the current objective value f_old = -tt_loglikelihood_row(isSparse, data_row, model_old, Pi) num_evals = 1 count = 1 @@ -1613,7 +1613,7 @@ def get_search_dir_pqnr( # noqa: PLR0913 lbfgsSize = delta_model.shape[1] # Determine active and free variables. - # TODO: is the bellow relevant? + # TODO: is the below relevant? # If epsActSet is zero, then the following works: # fixedVars = find((m_row == 0) & (grad' > 0)); # For the general case this works but is less clear and assumes m_row > 0: @@ -1747,7 +1747,7 @@ def calculate_phi( # noqa: PLR0913 Pi: np.ndarray, epsilon: float, ) -> np.ndarray: - """Calcualte Phi. + """Calculate Phi. Parameters ---------- diff --git a/pyttb/gcp/optimizers.py b/pyttb/gcp/optimizers.py index 300a7fcf..d41e1989 100644 --- a/pyttb/gcp/optimizers.py +++ b/pyttb/gcp/optimizers.py @@ -512,7 +512,7 @@ def lbfgsb_func_grad(vector: np.ndarray): lbfgsb_info["final_f"] = final_f lbfgsb_info["callback"] = vars(monitor) - # Unregister monitor in case of re-use + # Unregister monitor in case of reuse self._solver_kwargs["callback"] = monitor.callback # TODO big print output diff --git a/pyttb/hosvd.py b/pyttb/hosvd.py index e999c95a..47807f58 100644 --- a/pyttb/hosvd.py +++ b/pyttb/hosvd.py @@ -116,7 +116,7 @@ def hosvd( # noqa: PLR0912,PLR0913,PLR0915 ranks[k] = np.where(eigsum > eigsumthresh)[0][-1] if verbosity > 5: - print("Reverse cummulative sum of evals of Gram matrix:") + print("Reverse cumulative sum of evals of Gram matrix:") for i, a_sum in enumerate(eigsum): print_msg = f"{i: d}: {a_sum: 6.4f}" if i == ranks[k]: diff --git a/pyttb/ktensor.py b/pyttb/ktensor.py index 5c5f5571..51aa0d57 100644 --- a/pyttb/ktensor.py +++ b/pyttb/ktensor.py @@ -945,7 +945,7 @@ def to_tenmat( Mapping of column indices. cdims_cyclic: When only rdims is specified maps a single rdim to the rows and - the remaining dimensons span the columns. _fc_ (forward cyclic) + the remaining dimensions span the columns. _fc_ (forward cyclic) in the order range(rdims,self.ndims()) followed by range(0, rdims). _bc_ (backward cyclic) range(rdims-1, -1, -1) then range(self.ndims(), rdims, -1). @@ -1378,7 +1378,7 @@ def normalize( if sort: if self.ncomponents > 1: - # indices of srting in descending order + # indices of string in descending order p = np.argsort(self.weights)[::-1] self.arrange(permutation=p) @@ -2300,7 +2300,7 @@ def vis( # noqa: PLR0912, PLR0913 >>> fig, axs = K.vis(show_figure=False) # doctest: +ELLIPSIS >>> plt.close(fig) - Define a more realistic plot fuctions with x labels, + Define a more realistic plot functions with x labels, control relative widths of each plot, and set mode titles. diff --git a/pyttb/pyttb_utils.py b/pyttb/pyttb_utils.py index 2718dd93..b7fe0109 100644 --- a/pyttb/pyttb_utils.py +++ b/pyttb/pyttb_utils.py @@ -190,7 +190,7 @@ def tt_dimscheck( # noqa: PLR0912 # Check sizes to determine how to index multiplicands if P == M: # Case 1: Number of items in dims and number of multiplicands are equal; - # therfore, index in order of sdims + # therefore, index in order of sdims vidx = sidx else: # Case 2: Number of multiplicands is equal to the number of dimensions of @@ -545,7 +545,7 @@ def tt_sizecheck(shape: Tuple[int, ...], nargout: bool = True) -> bool: TT_SIZECHECK Checks that the shape is valid. TT_SIZECHECK(S) throws an error if S is not a valid shape tuple, - which means that it is a row vector with strictly postitive, + which means that it is a row vector with strictly positive, real-valued, finite integer values. Parameters @@ -820,7 +820,7 @@ def gather_wrap_dims( Mapping of column indices. cdims_cyclic: When only rdims is specified maps a single rdim to the rows and - the remaining dimensons span the columns. _fc_ (forward cyclic[1]_) + the remaining dimensions span the columns. _fc_ (forward cyclic[1]_) in the order range(rdims,self.ndims()) followed by range(0, rdims). _bc_ (backward cyclic[2]_) range(rdims-1, -1, -1) then range(self.ndims(), rdims, -1). diff --git a/pyttb/sptenmat.py b/pyttb/sptenmat.py index 7b374c62..3a3c13d5 100644 --- a/pyttb/sptenmat.py +++ b/pyttb/sptenmat.py @@ -253,7 +253,7 @@ def __deepcopy__(self, memo): return self.copy() def to_sptensor(self) -> ttb.sptensor: - """Contruct a :class:`pyttb.sptensor` from `:class:pyttb.sptenmat`. + """Construct a :class:`pyttb.sptensor` from `:class:pyttb.sptenmat`. Examples -------- diff --git a/pyttb/sptensor.py b/pyttb/sptensor.py index 509f2795..26a7fd5a 100644 --- a/pyttb/sptensor.py +++ b/pyttb/sptensor.py @@ -738,7 +738,7 @@ def to_sptenmat( Mapping of column indices. cdims_cyclic: When only rdims is specified maps a single rdim to the rows and - the remaining dimensons span the columns. _fc_ (forward cyclic[1]_) + the remaining dimensions span the columns. _fc_ (forward cyclic[1]_) in the order range(rdims,self.ndims()) followed by range(0, rdims). _bc_ (backward cyclic[2]_) range(rdims-1, -1, -1) then range(self.ndims(), rdims, -1). @@ -2029,7 +2029,7 @@ def __getitem__(self, item): # noqa: PLR0912, PLR0915 linear subscripts, returns a vector of `p` values. Any ambiguity results in executing the first valid case. This - is particularily an issue if `self.ndims == 1`. + is particularly an issue if `self.ndims == 1`. Examples -------- @@ -2368,7 +2368,7 @@ def _set_subscripts(self, key, value): # noqa: PLR0912 # Process Group A: Changing values if np.sum(idxa) > 0: self.vals[tf[idxa]] = newvals[idxa] - # Proces Group B: Removing Values + # Process Group B: Removing Values if np.sum(idxb) > 0: removesubs = loc[idxb] keepsubs = np.setdiff1d(range(0, self.nnz), removesubs) @@ -3119,7 +3119,7 @@ def __le__(self, other): Parameters ---------- other: - Oject to compare with. + Object to compare with. Examples -------- diff --git a/pyttb/tensor.py b/pyttb/tensor.py index 465522d9..f16994b3 100644 --- a/pyttb/tensor.py +++ b/pyttb/tensor.py @@ -456,7 +456,7 @@ def find(self) -> Tuple[np.ndarray, np.ndarray]: return subs, vals def to_sptensor(self) -> ttb.sptensor: - """Contruct a :class:`pyttb.sptensor` from `:class:pyttb.tensor`. + """Construct a :class:`pyttb.sptensor` from `:class:pyttb.tensor`. Returns ------- @@ -509,7 +509,7 @@ def to_tenmat( Mapping of column indices. cdims_cyclic: When only rdims is specified maps a single rdim to the rows and - the remaining dimensons span the columns. _fc_ (forward cyclic) + the remaining dimensions span the columns. _fc_ (forward cyclic) in the order range(rdims,self.ndims()) followed by range(0, rdims). _bc_ (backward cyclic) range(rdims-1, -1, -1) then range(self.ndims(), rdims, -1). @@ -1384,7 +1384,7 @@ def symmetrize( # noqa: PLR0912,PLR0915 combos.append(np.array(list(permutations(grps[i, :])))) combos = np.stack(combos) - # Create all the permuations to be averaged + # Create all the permutations to be averaged combo_lengths = [len(perm) for perm in combos] total_perms = prod(combo_lengths) sym_perms = np.tile(np.arange(0, n), [total_perms, 1]) @@ -2023,7 +2023,7 @@ def _set_subtensor(self, key, value): # noqa: PLR0912 not isinstance(entry, (float, int, np.generic)) for entry in element ): raise ValueError( - f"Entries for setitem must be numeric but recieved, {element}" + f"Entries for setitem must be numeric but received, {element}" ) sliceCheck.append(max(element)) else: @@ -2838,7 +2838,7 @@ def tendiag( ) -> tensor: """Create a tensor with elements along super diagonal. - If provided shape is too small the tensor will be enlarged to accomodate. + If provided shape is too small the tensor will be enlarged to accommodate. Parameters ---------- diff --git a/tests/gcp/test_fg_est.py b/tests/gcp/test_fg_est.py index 04f900f9..9699adc1 100644 --- a/tests/gcp/test_fg_est.py +++ b/tests/gcp/test_fg_est.py @@ -27,7 +27,7 @@ def test_estimate_helper(): all_indices = np.array(all_indices) values, _ = estimate_helper(factor_matrices, np.array(all_indices)) np.testing.assert_array_equal(full[all_indices], values) - # TODO should probably test Zexploded but thats a pain + # TODO should probably test Zexploded but that's a pain values, Z = estimate_helper(factor_matrices, np.array([])) assert values.size == 0 diff --git a/tests/test_cp_als.py b/tests/test_cp_als.py index 49d0cb2a..79c0a513 100644 --- a/tests/test_cp_als.py +++ b/tests/test_cp_als.py @@ -82,7 +82,7 @@ def test_cp_als_incorrect_init(capsys, sample_tensor): (M, Minit, output) = ttb.cp_als(T, 2, init="init") assert "The selected initialization method is not supported" in str(excinfo) - # incorrect size of intial ktensor + # incorrect size of initial ktensor Tshape_incorrect = list(T.shape) Tshape_incorrect[0] = Tshape_incorrect[0] + 1 Tshape_incorrect = tuple(Tshape_incorrect) diff --git a/tests/test_cp_apr.py b/tests/test_cp_apr.py index 1197d001..c6d88bf7 100644 --- a/tests/test_cp_apr.py +++ b/tests/test_cp_apr.py @@ -192,7 +192,7 @@ def test_cpapr_mu(capsys, sample_tensor1, default_init_ktensor): capsys.readouterr() assert np.isclose(M.full().data, ktensorSolnInstance.full().data).all() - # Assert given an inital guess of the final answer yields immediate convergence + # Assert given an initial guess of the final answer yields immediate convergence M, _, output = ttb.cp_apr( input_tensor=tensorInstance, rank=2, init=ktensorSolnInstance ) diff --git a/tests/test_ktensor.py b/tests/test_ktensor.py index a31f30a8..0dba3efb 100644 --- a/tests/test_ktensor.py +++ b/tests/test_ktensor.py @@ -212,7 +212,7 @@ def test_ktensor_arrange(sample_ktensor_2way): assert np.linalg.norm(K1.factor_matrices[0] - fm0) < 1e-8 assert np.linalg.norm(K1.factor_matrices[1] - fm1) < 1e-8 - # error, cannot shoft weight and permute simultaneously + # error, cannot shift weight and permute simultaneously with pytest.raises(AssertionError) as excinfo: K1.arrange(weight_factor=0, permutation=p) assert ( @@ -459,7 +459,7 @@ def test_ktensor_issymetric(sample_ktensor_2way, sample_ktensor_symmetric): assert np.array_equal(diffs, np.array([[0.0, 8.0], [0.0, 0]])) # should be symmetric - (datas, K1) = sample_ktensor_symmetric + _, K1 = sample_ktensor_symmetric assert K1.issymmetric() issym1, diffs1 = K1.issymmetric(return_diffs=True) assert np.array_equal(diffs1, np.array([[0.0, 0.0], [0.0, 0]])) @@ -849,7 +849,7 @@ def test_ktensor_score(): score, Aperm, flag, best_perm = A.score(B) assert "Size mismatch" in str(excinfo) - # invalid: number of compnents of first ktensor must be greater than or + # invalid: number of components of first ktensor must be greater than or # equal to number of components of second ktensor with pytest.raises(AssertionError) as excinfo: B = ttb.ktensor( diff --git a/tests/test_package.py b/tests/test_package.py index bde6b5c8..ba6301bc 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -54,3 +54,14 @@ def test_typing(): check=True, shell=True, ) + + +def test_spelling(): + """Confirm spelling is enforced""" + root_dir = os.path.dirname(os.path.dirname(__file__)) + toml_file = os.path.join(root_dir, "pyproject.toml") + subprocess.run( + f"codespell --toml {toml_file}", + check=True, + shell=True, + ) diff --git a/tests/test_sptensor.py b/tests/test_sptensor.py index 2417eb0a..4b7054d6 100644 --- a/tests/test_sptensor.py +++ b/tests/test_sptensor.py @@ -89,7 +89,7 @@ def function_handle(*args): assert sptensorInstance.shape == shape assert len(sptensorInstance.subs) == nz - # NZ as a propotion in [0,1) + # NZ as a proportion in [0,1) nz = 0.09375 sptensorInstance = ttb.sptensor.from_function(function_handle, shape, nz) assert np.array_equal(sptensorInstance.vals, function_handle()) @@ -487,7 +487,7 @@ def test_subtensor_growth(self, sample_sptensor): # Set empty tensor with sptensor via ambiguous slice emptyTensor = ttb.sptensor() - # TODO revist this after setitem cleanup. Probably won't support arbitrary slice on empty tensor + # TODO revisit this after setitem cleanup. Probably won't support arbitrary slice on empty tensor emptyTensor[:, :, :] = sptensorInstance assert emptyTensor.isequal(sptensorInstance) @@ -1165,7 +1165,7 @@ def test_sptensor__gt__(sample_sptensor): # Test comparison to tensor assert (sptensorInstance > sptensorInstance.full()).vals.size == 0 - # Test comparison to tensor of different sparsity patter + # Test comparison to tensor of different sparsity pattern denseTensor = sptensorInstance.full() denseTensor[1, 1, 2] = -1 assert np.array_equal( diff --git a/tests/test_tensor.py b/tests/test_tensor.py index 04e22b51..a7ab0abf 100644 --- a/tests/test_tensor.py +++ b/tests/test_tensor.py @@ -367,7 +367,7 @@ def test_subtensor(self, sample_tensor_2way): ttb.tensor(three_way_data)[two_slices].double(), three_way_data[two_slices], ) - # Combining slice with (multi-)integer indicies + # Combining slice with (multi-)integer indices assert np.array_equal( tensorInstance[np.array([0, 1]), :].data, tensorInstance.data[[0, 1], :] ) From 87ea5f5562befcc271931c575aea6a1f6e3e3dd4 Mon Sep 17 00:00:00 2001 From: Nick Johnson <24689722+ntjohnson1@users.noreply.github.com> Date: Sat, 14 Dec 2024 09:53:52 -0500 Subject: [PATCH 3/4] Internal: See if codespell precommit finds config. --- .pre-commit-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a53b97a9..f6dec37b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,4 +16,5 @@ repos: - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: - - id: codespell \ No newline at end of file + - id: codespell + args: [ --toml, "pyproject.toml"] \ No newline at end of file From 244069ed7b718ae5506cdada32809616352e1b37 Mon Sep 17 00:00:00 2001 From: Nick Johnson <24689722+ntjohnson1@users.noreply.github.com> Date: Sat, 14 Dec 2024 09:55:19 -0500 Subject: [PATCH 4/4] Internal: Found config. Now enable reading it --- .pre-commit-config.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f6dec37b..32bbcf63 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,4 +17,6 @@ repos: rev: v2.3.0 hooks: - id: codespell - args: [ --toml, "pyproject.toml"] \ No newline at end of file + args: [ --toml, "pyproject.toml"] + additional_dependencies: + - tomli \ No newline at end of file