Repository navigation
Description
Numpy matrices are quite notorious for, in hindsight, being a relatively bad design. One thing that is particularly annoying is that one cannot have stacks of matrices, which leads to work-around like those in #5085 -- https://github.com/astropy/astropy/pull/5085/files#diff-11cd3ae0a0afb774b06628d3912308a0R36
Currently, we only use np.matrix in a few places. I suggest we convert all of these to regular arrays so that they can be properly vectorized. I think none are exposed, so we should just be able to make the changes, but I thought I would get opinions before proceeding cc @eteq, @astrofrog, @StuartLittlefair.
p.s. A bit off-topic, but in many places in coordinates, we really need cartesian coordinates with x,y,z as last dimension rather than first. We could make an alternative property on CartesianCoordinate (say, get_xyz(self, xyz_axis=0) or to_vector) or perhaps even implement a Vector class (which CartesianCoordinate could be a subclass of). The slight relevance of the latter is that if we go that route, we obviously could also have a good Matrix class...
mhvk@swan:~$ find packages/astropy -name \*.py -exec grep np.matrix {} \; -print X = np.matrix(np.vstack([x, np.ones(len(x))]).T)
beta = np.linalg.inv(X.T * X) * X.T * np.matrix(y).T
packages/astropy/astropy/modeling/tests/test_fitters.py
cdelt = np.matrix(np.diag(self.wcs.get_cdelt()))
pc = np.matrix(self.wcs.get_pc())
cdelt = np.matrix(self.wcs.cd) * np.matrix(np.diag(self.wcs.cdelt))
cdelt = np.matrix(np.diag(self.wcs.cdelt))
pc = np.matrix(self.wcs.pc)
packages/astropy/astropy/wcs/wcs.py
return np.matrix(((c, s, 0),
return np.matrix(((c, 0, -s),
return np.matrix(((1, 0, 0),
return R.view(np.matrix)
packages/astropy/astropy/coordinates/angles.py
Activity
mhvk commentedon Jun 13, 2016
For reference, multi-D versions of
angles.rotation_matrixandangle_axiswork if one uses anndarraysubclass which overrides__mul__with__matmul__; see https://github.com/astropy/astropy/compare/master...mhvk:coord-no-np-matrix?expand=1In turn, that means these can work over the whole coordinate code if the places where matrices are multiplied are adjusted to make those use
np.matmul(or a suitably backported version for older numpy).eteq commentedon Jun 15, 2016
👍 to dropping
np.matrixin favor ofmatmul. I'm less sure about some of the more subtle consequences of the off-topic bit... (E.g., #4926 (comment))And if I understand right, this will prepare us to have an all-
@codebase whenever we decide only py 3.5 will be supported ;)mhvk commentedon Jun 15, 2016
@eteq, @StuartLittlefair - as proof is often in the pudding, I made two simple PRs that try either replacing
np.matrixwith a newAstropyMatrixthat can be multidimensional, or by usingmatmulinstead of multiplication where needed. I'm slightly leaning towards the latter, in particular because the erfa matrix routines always return regular arrays, so one might as well be similar to that.p.s. From a quick timing tests, it seems that even
np.einsum('...ij,...jk->...ik', m1, m2)is faster thanm1 * m2(wherem1andm2are matrices). So even just for performance reasons these are wins...StuartLittlefair commentedon Jun 16, 2016
Very nice @mhvk.
I just admit I'm torn by the two PRs. The former leads to much cleaner and readable code. However, it shares a fundamental flaw with the
matrixclass, which PEP465 puts better than I can:For this reason I think I prefer the second PR.
mhvk commentedon Jun 16, 2016
I think the most basic mistake of the
np.matrixclass (as well as my quickAstropyMatrixclass) was that the shape includes the shape of the matrix itself. I think much more logically it would just be the shape of the matrix stack. This would be similar for a vector (thinkCartesianRepresentation, where the shape reflects the shape of the coordinates, not also that there are three parts).But even so, I'm coming around to seeing the use of regular arrays and
matmulas the fastest and clearest path for now. And of course, as @eteq pointed out, once we only support python >=3.5, we can swap out all thosematmulwith@and then the notation looks OK again... (In the meantime, maybe I should create a new function that just calculates the products of a whole slew of matrices, asmatmul(matmul(matmul(a, b), c), d)really does look ugly;matrix_product(a, b, c, d)?mhvk commentedon Jul 29, 2016
fixed by #5104.
cdeil commentedon Sep 2, 2018
@mhvk - Use of
np.matrixin Astropy now shows up as a warning in the logs of affiliated package tests, e.g. for reproject:Looks like this is the only remaining use of
np.matrixin Astropy:@mhvk - Do you the use of
np.matrixinastropy/wcs/wcs.pyshould also be replaced?Actually, it seems to be only one method
pixel_scale_matrixwhere it's used:https://github.com/astropy/astropy/pull/2832/files#diff-d4c5b9e74c6c26000684075497033504R2741
Should be easy to rewrite using
np.arrayandnp.dot, no?MSeifert04 commentedon Sep 2, 2018
@cdeil I think we should discuss this in a new issue (or PR). The topic is related but the NumPy warning is relatively new, so I'm a bit hesitant to reopen this issue. But we shouldn't let that important comment linger in a closed issue.
mhvk commentedon Sep 3, 2018
Odd, I thought I had gotten them all! That's why I felt safe in introducing a warning in numpy... Anyway, it indeed shouldn't be too hard to write a PR that fixes this.
cdeil commentedon Sep 3, 2018
@mhvk - Do you have time to send a PR? I could also give it a try. Should at the end
np.dotornp.matmulbe called?mhvk commentedon Sep 3, 2018
@cdeil - if you could tackle it, that would be great - somehow in my test environment pytest is not catching the pending deprecation warnings.
And, yes, it should just entail removing
matrixand replacing the relevant*with@(allowed in python 3.5! though perhaps usingnp.matmulis better for backporting...)