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

ants.transform_index_to_physical_point doesn't accept floats #343

Open
rueberger opened this issue Mar 18, 2022 · 17 comments
Open

ants.transform_index_to_physical_point doesn't accept floats #343

rueberger opened this issue Mar 18, 2022 · 17 comments

Comments

@rueberger
Copy link
Contributor

Calling it with a list of floats yields:

TypeError: TransformIndexToPhysicalPointF3(): incompatible function arguments. The following argument types are supported:
    1. (arg0: capsule, arg1: List[List[int]]) -> List[List[float]]

However it seems that the underlying ITK method supports floats.

This would be a highly desirable feature, costs me half a voxel of accuracy. I'm happy to take a crack at it with some guidance, as I'm not experienced with capsules.

@stnava
Copy link
Member

stnava commented Mar 18, 2022

the index representation does not support float as it is by definition integer. there is something incorrect about your usage if you think that you need this.

@rueberger
Copy link
Contributor Author

Hi Brian,

As noted, the underlying implementation supports floats, there is no reason to force discretization of something that is an affine transformation under the hood. There are certainly reasons why someone would want to do such a thing, I touched on mine in #337.

@stnava
Copy link
Member

stnava commented Mar 18, 2022

again, I think you have a misunderstanding. the definition is integer type - not talking code here, this is the math. indices are discrete entities. the link you sent shows integer type. continuous indices are float/double - but those are just points with an identity mapping to index space. you are much better off just working with points or indices - there is no need for a continuous index.

@rueberger
Copy link
Contributor Author

The map from physical space to index space and it's inverse are R^3 -> R^3. I do not know what you mean, it's just an affine. ants.transform_physical_point_to_index is R^3 -> R^3, there is certainly no mathematical justification for ants.transform_index_to_physical_point to be Z^3 -> R^3, and there isn't a software justification either, as there is no loss of generality for those using integers.

@stnava
Copy link
Member

stnava commented Mar 18, 2022 via email

@rueberger
Copy link
Contributor Author

I don't see a useful distinction between the two. Would you accept a PR for this?

@stnava
Copy link
Member

stnava commented Mar 18, 2022

maybe - you would have to implement the point to continuous index transform.

indices map to a specific part of memory ( pixel / voxel ) - it has no concept of interpolation - this is important in code as it allows faster access to data. you should use indices when you want to set or get a data value in an image. otherwise, they are not useful. I almost never need to use index representation.

continuous indices are basically points without physical space.

@ntustison
Copy link
Member

Since ITK maintains a rigid distinction between "index" and "continuous index" types (and I think that should be continued here), perhaps a separate function should be created for continuous indices.

@rueberger
Copy link
Contributor Author

The point to continuous index transform is just a type cast. I understand the distinction I just don't think it's useful. As I said, I need the non-discretized affine. It doesn't cost anyone else anything, integers will be silently cast to floats behind the scenes.

I believe that ITK maintains a rigid distinction due to the nature of typing in C++. Note that they also have separate functions for the inverse physical to index transform, for which ants returns a float array and is the more relevant direction in regards to the discussion of the usefulness of the distinction between float and int indices (I still don't think it's useful though). In that direction (to index), you have to explicitly cast to int. If I'm coming from an index I have already done my indexing and it doesn't matter whether things are getting silently cast to floats behind the scenes.

Another perspective is that the silent cast to float is already happening somewhere in the pipeline for the affine matmul. Now or later, the cast has to happen.

@ntustison
Copy link
Member

So what's wrong with having a separate function?

@stnava
Copy link
Member

stnava commented Mar 18, 2022

indices map to a specific part of memory ( pixel / voxel ) - it has no concept of interpolation

index access is fast + cheap b/c there is no affine tx to worry about. it's closer to direct memory access ... which is the fastest there is. that is the reason for the distinction.

@stnava
Copy link
Member

stnava commented Mar 18, 2022

the reason I know this is b/c I was there in the early 2000s when the original itk implementation discussions were had.

@rueberger
Copy link
Contributor Author

This has nothing to do with indexing, it's just the inverse of the affine. This method isn't used anywhere in the codebase and isn't even documented.

Having a separate method would be redundant, confusing, and unpythonic. It's an implementation detail. We should take advantage of python being dynamically typed to make the library cleaner.

@stnava
Copy link
Member

stnava commented Mar 18, 2022 via email

@rueberger
Copy link
Contributor Author

As discussed in #337, I have a pipeline involving a third party displacement field defined in index space. The coordinates I am transforming have a measurement error considerably smaller than a voxel and I would like to retain that subvoxel precision.

@stnava
Copy link
Member

stnava commented Mar 18, 2022 via email

@rueberger
Copy link
Contributor Author

I would just do it on my fork as it is a quite minor change. I think we must be miscommunicating as this change would have no consequence to the end user or architecture of the library. I do not see a downside. One with an integer index could simple carry on using the method as they were before with no changes in behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants