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

Display 3D trajectories, with a grid interface #193

Open
wants to merge 69 commits into
base: master
Choose a base branch
from

Conversation

chaithyagr
Copy link
Member

No description provided.

chaithyagr and others added 30 commits April 26, 2024 14:45
This add "get_interpolators_from_fieldmap", supporting both real (B0 map only) and complex (Zmap = R2* + 1j * B0map) fields
in arbitrary dimension (2D and 3D). The routine supports both numpy / cupy arrays and torch tensors on CPU and GPU,
the latter requiring cupy due to limitations in torch.histogram / torch.histogramdd (pytorch/pytorch#69519).

Calculation uses time segmentation with uniform time samples and LS coefficients (using histogram).

Based on MIRT (https://github.com/JeffFessler/mirt/blob/main/mri/mri_exp_approx.m)
and its Python porting from MIRTORCH (https://github.com/guanhuaw/MIRTorch/blob/master/mirtorch/linear/mri.py)
and SigPy (https://github.com/mikgroup/sigpy/blob/main/sigpy/mri/util.py).
Avoid torch cuda test case if cupy is not available.
remove deprecated get_grad

Co-authored-by: Chaithya G R <[email protected]>
@chaithyagr
Copy link
Member Author

I will get a CLI also :P

@paquiteau paquiteau linked an issue Sep 22, 2024 that may be closed by this pull request
4 tasks
@chaithyagr chaithyagr self-assigned this Nov 8, 2024
@chaithyagr chaithyagr requested a review from Daval-G November 8, 2024 15:40
@chaithyagr
Copy link
Member Author

I seemed to have forgotten to add the example. Added it now. @Daval-G you are good to go for review whenever you get time.

@Daval-G
Copy link
Collaborator

Daval-G commented Nov 13, 2024

@chaithyagr I will have a look over the week-end

Copy link
Collaborator

@Daval-G Daval-G left a comment

Choose a reason for hiding this comment

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

It's a bunch of useful features that will make a great addition, but please try to make their use cases clearer to the readers.

Also remember to update the __init__.py files

examples/GPU/example_3d_trajectory_display.py Outdated Show resolved Hide resolved
examples/GPU/example_3d_trajectory_display.py Outdated Show resolved Hide resolved
examples/GPU/example_3d_trajectory_display.py Outdated Show resolved Hide resolved
examples/GPU/example_3d_trajectory_display.py Outdated Show resolved Hide resolved
Comment on lines 42 to 51
def create_grid(grid_type, title="", **kwargs):
fig, axs = plt.subplots(3, 3, figsize=(10, 10))
for i, (name, traj) in enumerate(trajectories.items()):
grid = get_gridded_trajectory(
traj, (64, 64, 64), grid_type=grid_type, traj_params=traj_params, **kwargs
)
plot_slices(axs[:, i], grid, title=name)
plt.tight_layout()
plt.suptitle(title)
plt.show()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not provide trajectories and traj_params as arguments but keep grid_type and title ? It makes it a bit of a pain to read here and below

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 moved title below. But I dont know if I understand you?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant that some of the variable used in the create_grid function are taken as argument and some others are just assumed to be there in the global context of execution, and I don't get the logic. Why not just put everything as an argument like a usual function ?

Comment on lines 78 to 82
data = grid_op.raw_op.adj_op(
np.tile(np.linspace(1, 10, shots.shape[1]), (shots.shape[0],)),
None,
True,
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't we want to provide actual time values ? It should be more explicit in the documentation

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also the output shape doesn't correspond to shape as expected when reading the documentation. I don't understand why this is part of that function since it doesn't relate to a grid

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why 1 to 10 ?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is just relative to get an understanding. Given that adjoint is not inverse, even if we give exact values, we cant expect it to be reflected the same way on image domain.
The shape would still be same as expected as we use grid_op which is set based on shape, right? Am I missing something?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Good point, thx !
Still curious, why 1 to 10 ? Why not just 0 to 1 ? At this point it doesn't matter much but I wonder


Parameters
----------
shots : ndarray
Copy link
Collaborator

Choose a reason for hiding this comment

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

The shots name isn't conventional in that part of the package

Copy link
Member Author

Choose a reason for hiding this comment

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

What would you recommend? traj ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

trajectory as in all other files

Comment on lines 15 to 25
def get_gridded_trajectory(
shots: np.ndarray,
shape: Tuple,
grid_type: str = "density",
osf: int = 1,
backend: str = "gpunufft",
traj_params: dict = None,
turbo_factor: int = 176,
elliptical_samp: bool = True,
threshold: float = 1e-3,
):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Overall, why have all of those features gathered into only one function ? Some of them are not related to grids.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also please add more comments to your code

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 think, all the features are related to gridding and how you want to "color" the trajectories on the grid.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's true, my bad !

src/mrinufft/trajectories/display3D.py Outdated Show resolved Hide resolved
src/mrinufft/trajectories/display3D.py Outdated Show resolved Hide resolved
@chaithyagr chaithyagr requested a review from Daval-G January 13, 2025 08:36
@chaithyagr
Copy link
Member Author

@Daval-G is there something else remaining or am I missing something here?

Copy link
Collaborator

@Daval-G Daval-G left a comment

Choose a reason for hiding this comment

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

Thanks for addressing most of my comments. I marked the ones done as resolved, so please have a look at all of the non-resolved ones (even to the ones marked as "outdated")

examples/GPU/example_3d_trajectory_display.py Outdated Show resolved Hide resolved
Comment on lines 42 to 51
def create_grid(grid_type, title="", **kwargs):
fig, axs = plt.subplots(3, 3, figsize=(10, 10))
for i, (name, traj) in enumerate(trajectories.items()):
grid = get_gridded_trajectory(
traj, (64, 64, 64), grid_type=grid_type, traj_params=traj_params, **kwargs
)
plot_slices(axs[:, i], grid, title=name)
plt.tight_layout()
plt.suptitle(title)
plt.show()
Copy link
Collaborator

Choose a reason for hiding this comment

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

I meant that some of the variable used in the create_grid function are taken as argument and some others are just assumed to be there in the global context of execution, and I don't get the logic. Why not just put everything as an argument like a usual function ?

Comment on lines 68 to 69
# Display the density of the trajectories, along the 3 mid-planes. For this, make `grid_type="density"`.
create_grid("density", "Sampling Density")
Copy link
Collaborator

Choose a reason for hiding this comment

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

@chaithyagr Thanks for addressing the second comment. The first one is still up to date, let me know your opinion


Parameters
----------
shots : ndarray
Copy link
Collaborator

Choose a reason for hiding this comment

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

trajectory as in all other files

examples/GPU/example_3d_trajectory_display.py Outdated Show resolved Hide resolved
src/mrinufft/trajectories/display3D.py Outdated Show resolved Hide resolved
src/mrinufft/trajectories/display3D.py Outdated Show resolved Hide resolved
Comment on lines 58 to 60
elliptical_samp : bool, optional
Whether to use elliptical sampling. Default is True.
This is useful while analyzing the k-space holes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I will rephrase: "Whether to use elliptical sampling" sounds odd, we already provide the trajectory so it's not like we will decide to use elliptical sampling. Is it that we tell if we sampled the k-space corners ? Then please explicit it, and tell why we need to provide it, what is it going to change ?

Please rephrase "This is useful while analyzing the k-space holes, especially if the k-space trajectory is expected to be elliptical sampling of k-space", we are missing words and the formulation could be simpler

Comment on lines 15 to 25
def get_gridded_trajectory(
shots: np.ndarray,
shape: Tuple,
grid_type: str = "density",
osf: int = 1,
backend: str = "gpunufft",
traj_params: dict = None,
turbo_factor: int = 176,
elliptical_samp: bool = True,
threshold: float = 1e-3,
):
Copy link
Collaborator

Choose a reason for hiding this comment

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

That's true, my bad !

src/mrinufft/trajectories/display3D.py Outdated Show resolved Hide resolved
@chaithyagr chaithyagr requested a review from Daval-G January 24, 2025 12:24
@chaithyagr
Copy link
Member Author

Hopefully have tackled all the queries. Its getting meesy to keep track of, @Daval-G please have a look, I did not resolve any comments.. and ofcourse, thank you for the review.

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

Successfully merging this pull request may close these issues.

Add trajectory plotting functions from SPARKLING
4 participants