PTB-MR / mrpro

MR image reconstruction and processing.
https://ptb-mr.github.io/mrpro/
Apache License 2.0
13 stars 3 forks source link

Add arithmetic for SpatialDimension #416

Open ckolbPTB opened 1 day ago

ckolbPTB commented 1 day ago

When saving our data to Dicom we need to recalculate positions and orientations. This would provide the arithemtic to do this more easily.

Current disadvantage: z,y,x were int | float | Tensor but are now always Tensor. This makes lots of things easier but would require quite some changes to our code (especially the SliceProjectionOp). We could of course keep it as int | float | Tensor but then we would need quite a few checks in the arithmetic part.

Another option would be to have z,y,x as int | float and then things like read_dirwould be a list of SpatialDimension objects.

github-actions[bot] commented 1 day ago

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/mrpro/algorithms/csm
   inati.py24196%44
   iterative_walsh.py15193%37
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.py422345%77–78, 88–98, 113–124, 138–149
   Reconstruction.py512453%41, 53–55, 79–86, 103–114
src/mrpro/data
   AcqInfo.py128298%174, 214
   CsmData.py28389%14, 84–86
   DcfData.py44882%17, 65, 77–82
   IData.py67987%119, 125, 129, 159–167
   IHeader.py75791%75, 109, 127–131
   KHeader.py1641790%24, 126–130, 157, 207, 218, 225–226, 229, 236, 275–286
   KNoise.py311552%39–52, 56–61
   KTrajectory.py69593%178–182
   MoveDataMixin.py1261985%14, 109, 125, 139–141, 202, 264–266, 279, 354, 358, 378–379, 381, 396–397, 399
   QData.py39782%42, 65–73
   SpatialDimension.py85396%80, 124, 175
   TrajectoryDescription.py14193%23
   acq_filters.py10190%47
src/mrpro/data/_kdata
   KData.py1051685%107–108, 117, 125, 179–180, 215, 220–221, 240–251
   KDataRemoveOsMixin.py29293%43, 45
   KDataSelectMixin.py20290%46, 62
   KDataSplitMixin.py48394%49, 79, 88
src/mrpro/data/traj_calculators
   KTrajectoryCalculator.py25292%23, 45
   KTrajectoryIsmrmrd.py13285%41, 50
   KTrajectoryPulseq.py29197%54
src/mrpro/operators
   CartesianSamplingOp.py50982%49–50, 55–56, 61–62, 88, 91, 114
   ConstraintsOp.py60297%46, 48
   EndomorphOperator.py51296%209, 213
   FiniteDifferenceOp.py27293%48, 113
   FourierOp.py77297%131, 192
   GridSamplingOp.py123993%60–61, 70–71, 78–79, 82, 84, 86
   LinearOperator.py80396%32, 131, 256
   Operator.py52198%21
   SliceProjectionOp.py166895%39, 46, 48, 54, 191, 212, 245, 285
   WaveletOp.py120596%152, 170, 205, 210, 233
   ZeroPadOp.py16194%30
src/mrpro/utils
   Rotation.py4532894%58–66, 106, 283, 368, 370, 397, 452, 457, 460, 475, 492, 497, 640, 645, 648, 664, 668, 742, 744, 752–753, 993, 1075
   filters.py62297%44, 49
   slice_profiles.py45687%18, 34, 111–114, 147
   sliding_window.py34197%34
   split_idx.py10280%43, 47
   summarize_tensorvalues.py11918%20–29
   zero_pad_or_crop.py31681%26, 30, 54, 57, 60, 63
TOTAL365529392% 

Tests Skipped Failures Errors Time
842 0 :zzz: 7 :x: 0 :fire: 57.318s :stopwatch:
fzimmermann89 commented 1 day ago

I would prefer to keep it as int|float|Tensor. Especially the int part is important for mypy. We use spatal dimensions for image sizes etc where only ints are valid. This should be type-checked.

fzimmermann89 commented 1 day ago

can you give an example where where this is required?

ckolbPTB commented 1 day ago

The image centre for dicom is the top left corner of the image so we have to do something like iheader.position + iheader.fov.x/2 * iheader.read_dir +... for every other dimension

would be nice if we could simply say iheader.position[idx,...] + iheader.fov.x/2 * iheader.read_dir[idx,...] +

currently that is not so straight forward.

Maybe we could add something like .as_xyz_tensor and .as_zyx_tensor?

fzimmermann89 commented 1 day ago

the original idea was to be explicit with x,y, and z. SoSpatialDimension(x=iheader.position.x[idx]+iheader.fov.x/2 * iheader.read_dir,... ) on purpose.

Nevertheless, I will do a draft with the correct type hints of this, so we can do it in your way. give me a couple minutes.

Furthermore, this might be a good opportunity to add a orientation as a Rotation property to the header. I put this to the side in the past, as we did not have any code accessing read_dir, etc anyways. This should do the the rotation of the fov then as iheader.rotation(iheader.fov)