Op repr updates#1394
Conversation
|
Checking updated PR...
Comment last updated on August 30, 2018 at 21:51 Hours UTC |
| Verify adjoint: | ||
|
|
||
| >>> g = div.range.element(data ** 2) | ||
| >>> adj_div_g = div.adjoint(g) |
|
Hey, could someone please have a look at this? It may seem like a daunting task with so many lines of diff, but it's actually not that much. Most of it is documentation and doesn't need that close of a look, in the sense that errors that slip through won't break anything. I've listed the most important changes above. |
|
I'll try to review this! |
adler-j
left a comment
There was a problem hiding this comment.
Overall good changes, but this really should have been 2 or even 3 different pull requests since it does wastly different things.
The only thing that needs discussion is the general addition of ranges where it does not seem obviously needed. Why has this been done?
| @@ -0,0 +1,14 @@ | |||
| [settings] | |||
There was a problem hiding this comment.
More spam of the top level directory. Why do we need this?
There was a problem hiding this comment.
That file slipped through, I'll ditch it.
| ) | ||
| """ | ||
| posargs = [self.domain] | ||
| optargs = [('range', self.range, self.domain ** self.domain.ndim), |
There was a problem hiding this comment.
That was a bug, yes. Copy 'n paste from Gradient I suppose.
| """ | ||
|
|
||
| from __future__ import print_function, division, absolute_import | ||
| from __future__ import absolute_import, division, print_function |
There was a problem hiding this comment.
Is this just standardization? If so (for next time), I'd prefer if it had a separate PR and was done to all of these occurances.
There was a problem hiding this comment.
Yeah I ran isort on the imports, so I don't have to think about where to put new imports. They'll be sorted and grouped nicely automatically.
I already did a few of the files in #1380, this part of the big PR #1276 just continues that. IMO the structure of the imports is better this way, compared to the "random" ordering we had before.
| -------- | ||
| >>> rect = odl.IntervalProd([0, 0], [1, 1]) | ||
| >>> fspace = odl.FunctionSpace(rect) | ||
| >>> part = odl.uniform_partition_fromintv(rect, shape=(4, 2)) |
There was a problem hiding this comment.
Do we need to use this very length version instead of the shorter options?
| >>> resampling_inv(resampling([0.0, 1.0, 0.0])) | ||
| uniform_discr(0.0, 1.0, 3).element([ 0., 1., 0.]) | ||
|
|
||
| However, it can fail in the other direction: |
|
|
||
| Examples | ||
| -------- | ||
| All rows and columns with an operator, i.e., domain and range |
There was a problem hiding this comment.
Wording could be improved. E.g. use something else that "with an operator", perhaps even drop it and only go with "Domain and range are inferred if there is at least one operator per row/column", or similar.
| [0, IdentityOperator(rn(3))]] | ||
| ) | ||
|
|
||
| Domain not completely determined (column with all zeros): |
There was a problem hiding this comment.
Mention that we need to give domain in this case.
| Domain not completely determined (column with all zeros): | ||
|
|
||
| >>> prod_op = odl.ProductSpaceOperator([[I, 0], | ||
| ... [I, 0]], domain=pspace) |
| Projection on the 0-th component: | ||
|
|
||
| >>> proj_adj = odl.ComponentProjectionAdjoint(pspace, 0) | ||
| >>> proj_adj = odl.ComponentProjection(pspace, 0).adjoint |
There was a problem hiding this comment.
Is there a reason we think users might not want this "embeding"? I'm not 100% sure we only want this accessible like this.
There was a problem hiding this comment.
I didn't really think about that. My assumption, given the name, was that it was just there as a "slave" to the "master" class ComponentProjection.
The class may certainly be of use on its own, if I think about it. How about we call it ComponentEmbedding? (It feels like we discussed this before.)
| np.random.uniform(size=self.shape) * 1j)) | ||
| else: | ||
| # TODO: return something that always works, like zeros or ones? | ||
| # TODO(kohr-h): return something that always works, like zeros |
There was a problem hiding this comment.
For non-numeric dtypes there is basically nothing left. What would zeros be for e.g. strings?
There was a problem hiding this comment.
I think zeros actually works with any type, meaningful or not.
>>> np.zeros(2, dtype=bool)
array([False, False], dtype=bool)
>>> np.zeros(2, dtype="U2")
array(['', ''],
dtype='<U2')
>>> np.ones(2, dtype=bool)
array([ True, True], dtype=bool)
>>> np.ones(2, dtype="U2")
array(['1', '1'],
dtype='<U2')There was a problem hiding this comment.
I'll be damned
>>> np.zeros(2, dtype=object)
array([0, 0], dtype=object)
There was a problem hiding this comment.
Yeah I think that one at least makes a bit of sense. Doesn't matter for us since we don't allow dtype=object. I personally find np.ones with string type hilarious.
| >>> resampling = odl.Resampling(coarse_discr, fine_discr) | ||
| >>> resampling_inv = resampling.inverse | ||
|
|
||
| The inverse is proper left inverse if the resampling goes from a |
| else: | ||
| return self._astype(dtype) | ||
|
|
||
| def asweighted(self, weighting): |
There was a problem hiding this comment.
How about this? It's going to be needed at some point, but not strictly here.
Another idea with this functionality would be to stuff it inside astype in kwargs, and to extend that function with more stuff that we might want to change. For instance interpolation, impl, or even trivial stuff like axis labels.
ac9aaa8 to
67f5b17
Compare
67f5b17 to
958e0a0
Compare
|
This is largely done, up to some open questions. |
|
I marked this as obsolete. It can be considered as a cherry-pick-from PR. So keeping it open until the changes are implemented some other way. |
(I just realized that this is based on the #1380 branch, so that should go in first.)Ready for review now.
Here's the next bunch of commits from #1276, kept to the minimum of space, discr and operator. Other submodules follow.
Biggest changes:
__repr__makes use of the new functionality with automatic line width adjustment (usingnp.get_printoptions()['linewidth']).__repr__methods now have a doctest, to make sure the code runs and does something useful at least in one case.rangegot it now....Basewith common children to inner class pattern to share context.Questionable stuff:
asweighted, not quite sure about thisreprdoesn't quite work that well with linewidth. The reason is that it callsrepr(parent_op)without knowing about the correct linewidth to use, and then appends its attribute string. I don't quite know how to solve this, but it doesn't feel like a pressing issue either.rangefor product space operators (e.g.,PointwiseInner), we need to consider spaces as compatible (in this narrow context) that have different weightings but are otherwise the same. Needs some thought about the consequences though.Additional changes/fixes:
Operatoris better now IMO__str__mostly, doesn't really add value very often. The baseOperatorclass defaults to__str__ = __repr__(not literally).isort.cfg.TODOs (after review):
numpy.getprintoptions()['precision'].isort.cfginto a separate PRto/dev/null