Skip to content

API: Add .mT attribute for arrays#23762

Merged
seberg merged 21 commits intonumpy:mainfrom
Kai-Striega:mT
Jun 21, 2023
Merged

API: Add .mT attribute for arrays#23762
seberg merged 21 commits intonumpy:mainfrom
Kai-Striega:mT

Conversation

@Kai-Striega
Copy link
Member

@Kai-Striega Kai-Striega commented May 15, 2023

This is the initial commit for adding an mT, or matrix transpose, attribute for arrays. It is still a work in progress and not done yet. Please note that this is my first time working on NumPy's C-API. The PR is mainly being submitted this early to confirm that I am on the right track.

Things that are still needed:

  • Release note
  • Masked array support
  • [ ] np.transpose
  • Check input dimensions in array_matrix_transpose_get and exit early if 1d array
  • Tests fail for higher dimensional arrays
  • Figure out the correct location for the tests

Another note; ndarray.T has a corresponding function np.transpose, as part of this PR should we add a corresponding function for .mT e.g. np.matrix_transpose? If this is the case, should I add a function to PyArray_MatrixTranspose to shape.c rather than defining the function inside getset.c as is done with the regular transpose function?

The lower dimensional (1d and 2d) tests compare the behaviour of `.mT` against
`.T` not swapaxes.
The test generates random shapes of a given length. This was previously used
with min_dims=3. This excludes arrays of dimension 0, 1, 2 which we want.
Instead we test all dimensions up to 7.
Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good start, will mark as draft for now if you don't mind, just unmark it when things are settling (not that I think there is much missing)!

@seberg seberg marked this pull request as draft May 15, 2023 15:23
This commit reduces the memory required by the test. Instead of explicitly
constructing an array of shape `shape`, we now construct only the last dim
and broadcast over that.
Hypothesis seems to be overkill for the provided situation. Use explicitly
defined values instead.
This commit causes `.mT` to raise a ValueError if ndim < 2. This is because
the matrix transpose is undefined for 0 or 1 dimensional arrays and having
it implemented may lead to confusion by users.
@rgommers
Copy link
Member

rgommers commented May 17, 2023

Thanks for working on this Kai!

Another note; ndarray.T has a corresponding function np.transpose, as part of this PR should we add a corresponding function for .mT e.g. np.matrix_transpose?

I'd say yes we want that (because of the analogue to .T and because the array API standard has it). It doesn't have to be in this PR though, if it's already large and easier to do as a follow-up - whatever seems best to you.

@charris
Copy link
Member

charris commented May 17, 2023

This will need a release note.

@Kai-Striega
Copy link
Member Author

Kai-Striega commented May 21, 2023

@rgommers I'm happy to work on it in this PR, but I'm still learning about NumPy internals, meaning that the commit history could become quite messy as I learn (of course I'll try my best to keep it clean). As a summary, I think we should match the functions for transpose i.e.:

  • np.matrix_transpose
  • np.ndarray.mT
  • np.ndaray.matrix_transpose
  • np.ma.matrix_transpose
  • np.ma.MaskedArray.mT
  • np.ma.MaskedArray.matrix_transpose

The next step for me is to add np.ndaray.matrix_transpose, which I am having some trouble with. What I have done so far is:

  • Moved the implementation into a new function (PyArray_MatrixTranspose) into numpy/core/src/multiarray/shape.c alongside PyArray_Transpose
  • Added a matrix_transpose entry to array_methods in numpy/core/src/multiarray/methods.c
  • Added PyArray_Transpose to the multiarray_funcs_api in numpy/core/code_generators/numpy_api.py

I'm not really sure if this is the right direction, or if we even want to add PyArray_MatrixTranspose to the C-API as (I think) I am doing.

@mattip
Copy link
Member

mattip commented May 21, 2023

I would not touch the NumPy C-API with this PR. It is enough to add the attribute to ndarray and ma. If in the future we wish to export it via the C-API, that can be another PR.

@rgommers
Copy link
Member

As a summary, I think we should match the functions for transpose i.e.:

We don't need/want both a .mT property and a .matrix_transpose method. It's duplicate and the plan is to trim down on ndarray methods. Just the property and the np.matrix_transpose function (and their MaskedArray equivalents) is enough.

@charris
Copy link
Member

charris commented May 21, 2023

I rather like the idea of an .mT property :) It would be useful to have a short way to call it in ...@...@... constructions.

This was decided to not be needed in the PR review.
Skipping CI as I know it doesn't work and don't need
CI to tell me that.

[skip ci]
@Kai-Striega
Copy link
Member Author

I've removed the code adding it to the C-API (I think) and stopped working on adding an ndarray.matrix_transpose method. I've kept the function PyArray_MatrixTranspose in shape.c as I want to be able to share it between ndarray.mT and np.matrix_transpose - this is causing the test to segfault compared to the earlier version.

I may need some help structuring the code so that I can share it between ndarray.mT and np.matrix_transpose.

@seberg
Copy link
Member

seberg commented May 22, 2023

You have to add the new function to a header file now and include it, probably. If you check the test failures, you see they fail on compiler warnings.

Copy link
Member

@BvB93 BvB93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add ndarray.mT annotations to the main init.pyi stub file? The type is identical to ndarray.T so you can just reuse that it:

numpy/numpy/__init__.pyi

Lines 986 to 987 in cc0abd7

@property
def T(self: _ArraySelf) -> _ArraySelf: ...

@Kai-Striega
Copy link
Member Author

Kai-Striega commented Jun 12, 2023

@seberg I've finally got the masked array implementation working! I'm not sure if it's done correctly, could you take a look at my last commit?

If it's right, I think I have three things left:

  • Take the reference to the function versions out of the release notes
  • Add the documentation
  • Add type hints for the masked array

numpy/ma/core.py Outdated

if self._mask is nomask:
# TODO: Should this return a masked_array or regular array?
return self._data.mT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A masked array. Otherwise, seems good. Although .transpose() has some _update_from_self stuff, it may make sense to just stick close to it in the off-chance it matters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm struggling to replicate .transpose() as it uses the function version, not the attribute. I haven't been figured out how to do this (yet) and will leave it for another PR - maybe I can come back and tidy it up then if there are problems?

@Kai-Striega Kai-Striega marked this pull request as ready for review June 12, 2023 13:03
@Kai-Striega
Copy link
Member Author

Kai-Striega commented Jun 12, 2023

@rgommers @seberg I've made the last changes that (I think) are needed, could I please ask you two for another review?

I've decided to leave the np.matrix_transpose function for now, I'll get to it in another PR

@InessaPawson InessaPawson added the triage review Issue/PR to be discussed at the next triage meeting label Jun 15, 2023
Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks, just should add the versionadded.

Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
@seberg seberg merged commit c6e1fd0 into numpy:main Jun 21, 2023
@seberg
Copy link
Member

seberg commented Jun 21, 2023

Thanks, lets put it in.

After merging, I noticed that the docs actually render slightly incorrectly. Not a big deal, but maybe you want to follow up?

I guess we need <BLANKLINE> or maybe its fine to just remove the blank line also.

@seberg seberg changed the title WIP: ENH: Add .mT attribute for arrays API: Add .mT attribute for arrays Jun 21, 2023
@Kai-Striega
Copy link
Member Author

Thanks that's my first C level contribution 👌. Let's hope for many more.

I'll follow up with the docs rendering properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

25 - WIP triage review Issue/PR to be discussed at the next triage meeting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants