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

espirit csm #95

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

espirit csm #95

wants to merge 3 commits into from

Conversation

fzimmermann89
Copy link
Member

A work-in-progress for espirit algorithm for cartesian images.
This is blocked until we have

  • a Cartesian FFT Operator (the code currently does an ifft on kdata.data) and
  • a notion of the ACS region ('calib' in the code).

Other TODOs/Notes:

  • image_shape should removed by using the shape of the result of the adjoint operator
  • the code is completely untested and will most likely contain logic and syntax errors.
  • not sure if the unfolds are correct.

The logic is derived from sigpy
we would have to check the license

Why implement it and not wrap sigpy?
Sigpy only works with Cartesian data and is sometimes annoying to install, as it uses cupy for the GPU implementation.

Closes #34

@fzimmermann89
Copy link
Member Author

@github-actions
Copy link
Contributor

github-actions bot commented Oct 14, 2023

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/mrpro/algorithms/csm
   inati.py24196%44
   walsh.py16194%34
src/mrpro/algorithms/dcf
   dcf_voronoi.py53492%15, 48–49, 76
src/mrpro/algorithms/optimizers
   adam.py20195%69
src/mrpro/algorithms/reconstruction
   DirectReconstruction.py281643%51–71, 85
   IterativeSENSEReconstruction.py13192%76
   Reconstruction.py502256%42, 54–56, 80–87, 104–113
   RegularizedIterativeSENSEReconstruction.py411759%96–100, 114–139
src/mrpro/data
   AcqInfo.py128398%26, 169, 207
   CsmData.py441468%17, 104–121, 125–127
   DcfData.py45882%18, 66, 78–83
   IData.py67987%119, 125, 129, 159–167
   IHeader.py75791%75, 109, 127–131
   KHeader.py1531292%25, 119–123, 150, 199, 210, 217–218, 221, 228
   KNoise.py311552%39–52, 56–61
   KTrajectory.py69593%178–182
   MoveDataMixin.py1371887%15, 113, 129, 143–145, 207, 305–307, 320, 399, 419–420, 422, 437–438, 440
   QData.py39782%42, 65–73
   Rotation.py6743595%100, 198, 335, 433, 477, 495, 581, 583, 592, 626, 628, 691, 768, 773, 776, 791, 808, 813, 889, 1077, 1082, 1085, 1109, 1113, 1240, 1242, 1250–1251, 1315, 1397, 1690, 1846, 1881, 1885, 1996
   SpatialDimension.py2302091%33, 103, 135, 141, 261–263, 276–278, 312, 330, 343, 356, 369, 382, 391–392, 407, 416
   acq_filters.py12192%47
src/mrpro/data/_kdata
   KData.py1341887%109–110, 125, 132, 142, 150, 204–205, 243, 248–249, 268–279
   KDataRemoveOsMixin.py29293%44, 46
   KDataSelectMixin.py19289%48, 63
   KDataSplitMixin.py48394%53, 84, 93
src/mrpro/data/traj_calculators
   KTrajectoryCalculator.py25292%23, 45
   KTrajectoryIsmrmrd.py13285%41, 50
   KTrajectoryPulseq.py29197%54
src/mrpro/operators
   CartesianSamplingOp.py89397%118, 157, 280
   ConstraintsOp.py60297%46, 48
   EndomorphOperator.py65297%228, 234
   FiniteDifferenceOp.py27293%40, 105
   FourierOp.py157398%263, 381, 386
   Functional.py71593%20–22, 117, 119
   GridSamplingOp.py136993%72–73, 82–83, 90–91, 94, 96, 98
   LinearOperator.py1711293%55, 91, 190, 220, 261, 270, 278, 287, 295, 320, 418, 423
   LinearOperatorMatrix.py1581690%82, 119, 152, 161, 166, 175–178, 191–194, 203, 215, 304, 331, 359
   MultiIdentityOp.py13285%43, 48
   Operator.py78297%25, 74
   ProximableFunctionalSeparableSum.py39392%50, 103, 110
   SliceProjectionOp.py173895%44, 61, 63, 69, 206, 227, 260, 300
   WaveletOp.py120596%152, 170, 205, 210, 233
   ZeroPadOp.py16194%30
src/mrpro/utils
   filters.py62297%44, 49
   slice_profiles.py46687%20, 36, 113–116, 149
   sliding_window.py34197%34
   split_idx.py10280%43, 47
   summarize_tensorvalues.py11282%23, 25
   typing.py181139%8–23
   zero_pad_or_crop.py31681%26, 30, 54, 57, 60, 63
TOTAL490835293% 

Tests Skipped Failures Errors Time
2010 0 💤 1 ❌ 0 🔥 2m 3s ⏱️

@fzimmermann89 fzimmermann89 marked this pull request as draft October 17, 2023 19:06
@fzimmermann89 fzimmermann89 changed the title (DRAFT) initial draft espirit csm espirit csm Oct 17, 2023
@fzimmermann89 fzimmermann89 marked this pull request as ready for review October 19, 2023 09:06
@fzimmermann89 fzimmermann89 marked this pull request as draft October 19, 2023 09:07
_, S, VH = torch.linalg.svd(mat, full_matrices=False)

# Get kernels
kernels = rearrange(VH[S > thresh * S.max()], 'n (coils cba) -> n coils cba')
Copy link
Collaborator

@SherineBrahma SherineBrahma Feb 27, 2024

Choose a reason for hiding this comment

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

Background:

ESPIRiT paper

In eq.(9), we need to calculate V_|| that is associated with the row space of the Calibration matrix A. This is later used to construct the forward matrix W. In principle, V_|| is obtained from V by trimming off the row vectors corresponding to zero eigen-values. However, here, they have done it based on this mask: "S > thresh * S.max()". This makes sense as eigen-values may not go to 0 because of the presence of noise.

Problem:
This trimming of VH[S > thresh * S.max()] based on the mask (S > thresh * S.max()) is not supported inside "vmap" operations. I have a feeling that operations like this change the size of the matrix, and that poses challenges to perform batch operations, given that all elements of the batches should have the same shape.

Possible Solution:
If we want to adopt a parallelized approach like before, maybe it makes sense to perform vmap only till the SVD is calculated, since SVD is usually a computationally demanding algorithm for large matrices. Thereafter, we can use loops to construct V_||'s, where different V_||'s can have different shapes based on the batched SVD results. For this, I can use the smap function defined here. However, based on the layout of this file (define _iterative_walsh_csm and then estimate_walsh, define estimate_espirit and then _espirit_csm) , I am not sure if opening up this code to perform first part in one place (SVD calculation using vmap), while performing the other part in another place (forward operation using loops), will break the stye of the code.

If we want to retain the original coding style, I can use the smap function over the whole _espirit_csm function where the SVD is included, but then we would not be parallelizing the SVD.

@ckolbPTB

Copy link
Member Author

@fzimmermann89 fzimmermann89 Feb 27, 2024

Choose a reason for hiding this comment

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

I would just switch to fully serial calculation of the csms for different others using smap.

@SherineBrahma SherineBrahma requested review from ckolbPTB and removed request for ckolbPTB February 27, 2024 10:35
Copy link
Contributor

github-actions bot commented Nov 13, 2024

📚 Documentation

📁 Download as zip
🔍 View online

@lrlunin lrlunin removed their assignment Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

Espirit CSM Calculation
4 participants