Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linearized deformations second take #488

Merged
merged 13 commits into from
Aug 16, 2016
Merged

Conversation

adler-j
Copy link
Member

@adler-j adler-j commented Jul 11, 2016

Second take at linearized deformations. I've cleaned up most of the implementation and updated the doc, should be ready for final review @chongchenmath, @kohr-h, @ozanoktem .

@adler-j
Copy link
Member Author

adler-j commented Jul 11, 2016

Cleaned up commit history and implementation, also rebased to master. Should be reviewable.


return PointwiseInner(self.domain, def_grad)

def __repr__(self):
Copy link
Member

Choose a reason for hiding this comment

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

What is this mean?

Copy link
Member Author

Choose a reason for hiding this comment

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

repr is short for representation and is intended to give a representation of the object. It is called when you write things like

>>> space = odl.rn(3)
>>> space
rn(3)  # Here repr is called

and can also be explicitly invoked through the repr function

>>> space = odl.rn(3)
>>> print(repr(space))
rn(3)

You can read some more in the official documentation.

Copy link
Member Author

@adler-j adler-j Jul 11, 2016

Choose a reason for hiding this comment

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

Generally, you should be able to create the object from the repr string, but this is not always possible.

>>> np.array([1, 2, 3, 4, 5])
array([1, 2, 3, 4, 5])  # can recerate the array from this
>>> np.eye(5)
array([[ 1.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  1.]])  # can still recreate the array
>>> np.eye(50)
array([[ 1.,  0.,  0., ...,  0.,  0.,  0.],
       [ 0.,  1.,  0., ...,  0.,  0.,  0.],
       [ 0.,  0.,  1., ...,  0.,  0.,  0.],
       ..., 
       [ 0.,  0.,  0., ...,  1.,  0.,  0.],
       [ 0.,  0.,  0., ...,  0.,  1.,  0.],
       [ 0.,  0.,  0., ...,  0.,  0.,  1.]])  # array too big, cannot recreate it

ODL generally works the same:

>>> odl.vector([1., 2, 3, 4, 5])
rn(5).element([1.0, 2.0, 3.0, 4.0, 5.0])
>>> odl.vector([1.] * 100)
rn(100).element([1.0, 1.0, 1.0, ..., 1.0, 1.0, 1.0])

Copy link
Member

@chongchenmath chongchenmath Jul 11, 2016

Choose a reason for hiding this comment

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

discr_space = odl.uniform_discr([-1, -1], [1, 1], (100, 100), interp='linear')
template = odl.phantom.cuboid(discr_space, [-0.5, -0.5], [-0.25, 0])
fixed_templ_op = odl.deform.LinDeformFixedTempl(template)

Without explicit __repr__()

>>> fixed_templ_op
LinDeformFixedTempl: ProductSpace(uniform_discr([-1.0, -1.0], [1.0, 1.0], [100, 100],
interp=u'linear'), 2) -> uniform_discr([-1.0, -1.0], [1.0, 1.0], [100, 100], interp=u'linear')

With explicit __repr__()

>>> fixed_templ_op
LinDeformFixedTempl(uniform_discr([-1.0, -1.0], [1.0, 1.0], [100, 100], interp=u'linear')
.element([[0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0],
 [0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0],
 [0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0],
 ...,
 [0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0],
 [0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0],
 [0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0]]))

It seems the former is more clear. Maybe I am wrong.

Edit: @adler-j typeset python

Copy link
Member Author

Choose a reason for hiding this comment

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

While you are correct in some sense, it depends on your definition of clear. In python there are two "print" statements, __str__ and __repr__. __str__ is intended to give a short representation of the object so users know what is meant, while __repr__ should be used for debugging and be more precise.

Here I only implemented __repr__, mostly because I was lazy. We could want to implement __str__ as well however.

This was referenced Jul 11, 2016
'instance if `domain` is None, got {!r}'
''.format(template))

domain = template.space.tangent_space
Copy link
Member

Choose a reason for hiding this comment

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

In differential geometry, one can attach to every point x of a differentiable manifold a tangent space. Here we attach a tangent_space to a space. It seems using space.tangent_space is not exact. Probably tangent bundle?

Copy link
Member Author

Choose a reason for hiding this comment

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

Since the space is flat they should be equivalent, but sure, the naming here is not perfect. We may need some more thought on it.

Copy link
Member

Choose a reason for hiding this comment

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

Yes. It's quite a geometric concept here. How about vector filed space, short for vf_space or more explicit name?

Copy link
Contributor

Choose a reason for hiding this comment

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

The source for the discussion regarding the notion of tangent space is that ODL lacks a notion of manifold (curved space). In ODL one has either a set or a vector space, the notion of a. manifold does not exist. We have already encountered the need to handle manifolds since data space in tomography is a non-Euclidian manifold. The operations required for points (=tomographic data) on such manifolds could however be rephrased as operations on the underlying coordinate space (products of intervals), ignoring the fact that a single coordinate space is insufficient as an atlas. Now, dealing with deformations requires us yet again to handle points (=vector fields) in curved spaces, i.e. manifolds. One option is to try to recast the operations to the underlying coordinate spaces, e.g. assuming a RKHS. Another is to introduce notions manifold in ODL with a tangent bundle. The latter seems to be quite time consuming though.

Copy link
Member

Choose a reason for hiding this comment

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

An option, and I think that's what @adler-j was trying to achieve, is to represent the space for the vector fields directly, without having the notion of manifolds. That's of course a bit limiting, as for the manifolds in acquisition geometries, but from my perspective it's a sufficient solution and can be handled quite smoothly with the means we have currently. I don't think we necessarily need RHKS to do that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well for the fixed template style deformations we need a proper domain for the deformations., and in the fixed deformation case we need to be able to give it as input. Basically we need a name for the space

ProductSpace(space.astype(space.real_dtype), space.ndim)

I picked tangent_space since it felt natural, but as @chongchenmath noted this may not be future proof since it is only correct for flat spaces.

@kohr-h was really on spot on what we try to achieve here. RKHS has nothing to do with this one and probably shouldn't need to be involved for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are we talking about the set of deformations or the set of vector/velocity fields generating deformations? The set of deformations is not a vector space, it is a semi group and a Lie group at best. The set of vector/velocity fields generating deformations is however a vector space, which in some theoretical frameworks can be interpreted as the tangent space to the Lie group of deformations. RKHS was mentioned as an example of how this Lie group could be equipped coordinates. So, what are we trying to name here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Are we talking about the set of deformations or the set of vector/velocity fields generating deformations?

We're talking about "the set of vector/velocity fields generating deformations".

Copy link
Member

Choose a reason for hiding this comment

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

As I suggested, one abbreviation of vector field space is probably a proper choice here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree, something along those lines would be good.

@adler-j adler-j force-pushed the linearized_deformations_simplified branch 3 times, most recently from efa5d30 to eb3a60b Compare July 14, 2016 09:04
@chongchenmath chongchenmath force-pushed the linearized_deformations_simplified branch from dc334e9 to cd5fd85 Compare July 15, 2016 10:52
----------
template : `DiscreteLpVector`
Template to be deformed by a displacement field.
displacement : `ProductSpace` element
Copy link
Member Author

Choose a reason for hiding this comment

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

ProductSpace of DiscreteLp element

Copy link
Member

Choose a reason for hiding this comment

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

done.

'instance, got {!r}'.format(displacement[0]))

if templ_space is None:
templ_space = displacement[0].space
Copy link
Member Author

Choose a reason for hiding this comment

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

While equivalent, I feel it would be better to write displacement.space[0]

@adler-j
Copy link
Member Author

adler-j commented Aug 12, 2016

This is starting to look very good, I only found some minor style issues. We should be able to merge soon.

----------
template : `DiscreteLpVector`
Template to be deformed by a displacement field.
displacement : `ProductSpace` of `DiscreteLp` element
Copy link
Member

Choose a reason for hiding this comment

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

Should be same as below

@kohr-h
Copy link
Member

kohr-h commented Aug 15, 2016

I added an (approximate) inverse to the fixed-displacement operator since we're using it in the adjoint anyway. Fixed the comments.

@kohr-h kohr-h force-pushed the linearized_deformations_simplified branch from c004719 to b5a5106 Compare August 16, 2016 11:56
@kohr-h
Copy link
Member

kohr-h commented Aug 16, 2016

Cleaned up the commit history a bit, will merge after tests have passed.

chongchenmath and others added 13 commits August 16, 2016 14:12
* Add linearized deformation operators
* Add tests for the linearized deformations
* Add examples of linerized deformations
Examples:
- Better text, more informative comments and a more interesting
  displacement field in the deformation examples

linear_deform.py:
- Simplified imports
- Improved docstrings, mostly adding missing documentation and
  some reformulations
- Mathematical descriptions added to both operators
- Removed optional `domain` parameter from the fixed-template
  operator since it complicates things and doesn't add much.
- In the fixed displacement variant, it is needed to be able
  to support complex template spaces - here the support for
  implicitly discretizing a displacement field was removed
  for reasons of simplicity. Further, the parameter is now called
  `templ_space` since it is both domain and range.
- Public properties for the fixed attributes `template` or
  `displacement` added, resp.

lp_discr.py:
- `_interp_by_axis` -> `__interp_by_axis`
- Go back to old version of real space calculation in `DiscreteLp`.
  The current one arbitrarily added `self.real_space` to an instance.

Tests:
- Adapt to code changes
@kohr-h kohr-h force-pushed the linearized_deformations_simplified branch from b5a5106 to b8daded Compare August 16, 2016 12:50
@kohr-h kohr-h merged commit e8b99b8 into master Aug 16, 2016
@kohr-h kohr-h deleted the linearized_deformations_simplified branch August 16, 2016 13:03
@kohr-h kohr-h mentioned this pull request Aug 18, 2016
2 tasks
@kohr-h kohr-h removed the merge? label Sep 21, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants