Skip to content

Commit

Permalink
Merge branch 'main' into ids
Browse files Browse the repository at this point in the history
  • Loading branch information
fzimmermann89 authored Nov 11, 2024
2 parents 071b049 + 191ab06 commit 265339a
Show file tree
Hide file tree
Showing 31 changed files with 1,087 additions and 161 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,15 @@ jobs:
run: |
VERSION=${{ needs.build-testpypi-package.outputs.version }}
SUFFIX=${{ needs.build-testpypi-package.outputs.suffix }}
python -m pip install mrpro==$VERSION$SUFFIX --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/
for i in {1..3}; do
if python -m pip install mrpro==$VERSION$SUFFIX --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/; then
echo "Package installed successfully."
break
else
echo "Attempt $i failed. Retrying in 10 seconds..."
sleep 10
fi
done
build-pypi-package:
name: Build Package for PyPI
Expand Down
9 changes: 4 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: check-added-large-files
- id: check-docstring-first
- id: check-merge-conflict
- id: check-yaml
- id: check-toml
Expand All @@ -15,14 +14,14 @@ repos:
- id: mixed-line-ending

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
rev: v0.7.2
hooks:
- id: ruff # linter
args: [--fix]
- id: ruff-format # formatter

- repo: https://github.com/crate-ci/typos
rev: v1.25.0
rev: v1.27.0
hooks:
- id: typos

Expand All @@ -34,7 +33,7 @@ repos:
exclude: ^tests/

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.11.2
rev: v1.13.0
hooks:
- id: mypy
pass_filenames: false
Expand Down
8 changes: 4 additions & 4 deletions examples/direct_reconstruction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
"\n",
"import requests\n",
"\n",
"data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')\n",
"response = requests.get(zenodo_url + fname, timeout=30)\n",
"data_file.write(response.content)\n",
"data_file.flush()"
"with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:\n",
" response = requests.get(zenodo_url + fname, timeout=30)\n",
" data_file.write(response.content)\n",
" data_file.flush()"
]
},
{
Expand Down
8 changes: 4 additions & 4 deletions examples/direct_reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

import requests

data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()
with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()

# %% [markdown]
# ### Image reconstruction
Expand Down
8 changes: 4 additions & 4 deletions examples/iterative_sense_reconstruction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
"\n",
"import requests\n",
"\n",
"data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')\n",
"response = requests.get(zenodo_url + fname, timeout=30)\n",
"data_file.write(response.content)\n",
"data_file.flush()"
"with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:\n",
" response = requests.get(zenodo_url + fname, timeout=30)\n",
" data_file.write(response.content)\n",
" data_file.flush()"
]
},
{
Expand Down
8 changes: 4 additions & 4 deletions examples/iterative_sense_reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

import requests

data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()
with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()

# %% [markdown]
# ### Image reconstruction
Expand Down
22 changes: 12 additions & 10 deletions examples/pulseq_2d_radial_golden_angle.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@
"cell_type": "code",
"execution_count": null,
"id": "d16f41f1",
"metadata": {},
"metadata": {
"lines_to_next_cell": 2
},
"outputs": [],
"source": [
"# define zenodo records URL and create a temporary directory and h5-file\n",
"zenodo_url = 'https://zenodo.org/records/10854057/files/'\n",
"fname = 'pulseq_radial_2D_402spokes_golden_angle_with_traj.h5'\n",
"data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')"
"fname = 'pulseq_radial_2D_402spokes_golden_angle_with_traj.h5'"
]
},
{
Expand All @@ -50,9 +51,10 @@
"outputs": [],
"source": [
"# Download raw data using requests\n",
"response = requests.get(zenodo_url + fname, timeout=30)\n",
"data_file.write(response.content)\n",
"data_file.flush()"
"with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:\n",
" response = requests.get(zenodo_url + fname, timeout=30)\n",
" data_file.write(response.content)\n",
" data_file.flush()"
]
},
{
Expand Down Expand Up @@ -125,10 +127,10 @@
"# download the sequence file from zenodo\n",
"zenodo_url = 'https://zenodo.org/records/10868061/files/'\n",
"seq_fname = 'pulseq_radial_2D_402spokes_golden_angle.seq'\n",
"seq_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.seq')\n",
"response = requests.get(zenodo_url + seq_fname, timeout=30)\n",
"seq_file.write(response.content)\n",
"seq_file.flush()"
"with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.seq') as seq_file:\n",
" response = requests.get(zenodo_url + seq_fname, timeout=30)\n",
" seq_file.write(response.content)\n",
" seq_file.flush()"
]
},
{
Expand Down
17 changes: 9 additions & 8 deletions examples/pulseq_2d_radial_golden_angle.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
# define zenodo records URL and create a temporary directory and h5-file
zenodo_url = 'https://zenodo.org/records/10854057/files/'
fname = 'pulseq_radial_2D_402spokes_golden_angle_with_traj.h5'
data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')


# %%
# Download raw data using requests
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()
with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()

# %% [markdown]
# ### Image reconstruction using KTrajectoryIsmrmrd
Expand Down Expand Up @@ -62,10 +63,10 @@
# download the sequence file from zenodo
zenodo_url = 'https://zenodo.org/records/10868061/files/'
seq_fname = 'pulseq_radial_2D_402spokes_golden_angle.seq'
seq_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.seq')
response = requests.get(zenodo_url + seq_fname, timeout=30)
seq_file.write(response.content)
seq_file.flush()
with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.seq') as seq_file:
response = requests.get(zenodo_url + seq_fname, timeout=30)
seq_file.write(response.content)
seq_file.flush()

# %%
# Read raw data and calculate trajectory using KTrajectoryPulseq
Expand Down
8 changes: 4 additions & 4 deletions examples/regularized_iterative_sense_reconstruction.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
"\n",
"import requests\n",
"\n",
"data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')\n",
"response = requests.get(zenodo_url + fname, timeout=30)\n",
"data_file.write(response.content)\n",
"data_file.flush()"
"with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:\n",
" response = requests.get(zenodo_url + fname, timeout=30)\n",
" data_file.write(response.content)\n",
" data_file.flush()"
]
},
{
Expand Down
8 changes: 4 additions & 4 deletions examples/regularized_iterative_sense_reconstruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

import requests

data_file = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5')
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()
with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix='.h5') as data_file:
response = requests.get(zenodo_url + fname, timeout=30)
data_file.write(response.content)
data_file.flush()

# %% [markdown]
# ### Image reconstruction
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ testpaths = ["tests"]
filterwarnings = [
"error",
"ignore:'write_like_original':DeprecationWarning:pydicom:",
"ignore:Anomaly Detection has been enabled:UserWarning", #torch.autograd
]
addopts = "-n auto"
markers = ["cuda : Tests only to be run when cuda device is available"]
Expand Down
2 changes: 1 addition & 1 deletion src/mrpro/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.241015
0.241029
11 changes: 3 additions & 8 deletions src/mrpro/algorithms/optimizers/cg.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,6 @@ def cg(
if torch.vdot(residual.flatten(), residual.flatten()) == 0:
return solution

# squared tolerance;
# (we will check ||residual||^2 < tolerance^2 instead of ||residual|| < tol
# to avoid the computation of the root for the norm)
tolerance_squared = tolerance**2

# dummy value. new value will be set in loop before first usage
residual_norm_squared_previous = None

Expand All @@ -95,7 +90,7 @@ def cg(
residual_norm_squared = torch.vdot(residual_flat, residual_flat).real

# check if the solution is already accurate enough
if tolerance != 0 and (residual_norm_squared < tolerance_squared):
if tolerance != 0 and (residual_norm_squared < tolerance**2):
return solution

if iteration > 0:
Expand All @@ -105,8 +100,8 @@ def cg(
# update estimates of the solution and the residual
(operator_conjugate_vector,) = operator(conjugate_vector)
alpha = residual_norm_squared / (torch.vdot(conjugate_vector.flatten(), operator_conjugate_vector.flatten()))
solution += alpha * conjugate_vector
residual -= alpha * operator_conjugate_vector
solution = solution + alpha * conjugate_vector
residual = residual - alpha * operator_conjugate_vector

residual_norm_squared_previous = residual_norm_squared

Expand Down
14 changes: 5 additions & 9 deletions src/mrpro/data/AcqInfo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Acquisition information dataclass."""

from collections.abc import Callable, Sequence
from collections.abc import Sequence
from dataclasses import dataclass

import ismrmrd
Expand Down Expand Up @@ -206,17 +206,13 @@ def tensor_2d(data: np.ndarray) -> torch.Tensor:
data_tensor = data_tensor[None, None]
return data_tensor

def spatialdimension_2d(
data: np.ndarray, conversion: Callable[[torch.Tensor], torch.Tensor] | None = None
) -> SpatialDimension[torch.Tensor]:
def spatialdimension_2d(data: np.ndarray) -> SpatialDimension[torch.Tensor]:
# Ensure spatial dimension is (k1*k2*other, 1, 3)
if data.ndim != 2:
raise ValueError('Spatial dimension is expected to be of shape (N,3)')
data = data[:, None, :]
# all spatial dimensions are float32
return (
SpatialDimension[torch.Tensor].from_array_xyz(torch.tensor(data.astype(np.float32))).apply_(conversion)
)
return SpatialDimension[torch.Tensor].from_array_xyz(torch.tensor(data.astype(np.float32)))

acq_idx = AcqIdx(
k1=tensor(idx['kspace_encode_step_1']),
Expand Down Expand Up @@ -251,10 +247,10 @@ def spatialdimension_2d(
flags=tensor_2d(headers['flags']),
measurement_uid=tensor_2d(headers['measurement_uid']),
number_of_samples=tensor_2d(headers['number_of_samples']),
patient_table_position=spatialdimension_2d(headers['patient_table_position'], mm_to_m),
patient_table_position=spatialdimension_2d(headers['patient_table_position']).apply_(mm_to_m),
phase_dir=spatialdimension_2d(headers['phase_dir']),
physiology_time_stamp=tensor_2d(headers['physiology_time_stamp']),
position=spatialdimension_2d(headers['position'], mm_to_m),
position=spatialdimension_2d(headers['position']).apply_(mm_to_m),
read_dir=spatialdimension_2d(headers['read_dir']),
sample_time_us=tensor_2d(headers['sample_time_us']),
scan_counter=tensor_2d(headers['scan_counter']),
Expand Down
Loading

0 comments on commit 265339a

Please sign in to comment.