Skip to content

Commit

Permalink
Merge pull request #25 from mjt320/add_signal_to_concentration
Browse files Browse the repository at this point in the history
Add initial signal to concentration contribution
  • Loading branch information
LucyKershaw authored Apr 8, 2024
2 parents be31fe6 + 55f8a2f commit 48dff26
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 5 deletions.
27 changes: 27 additions & 0 deletions docs/examples/signal/plot_signal_R1_to_s_linear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
==============
Linear model for relationship between R1 and magnitude signal
==============
Demonstrating the linear model for relationship between R1 and magnitude signal, s = k.R1
"""

# %%
# Import necessary packages
import numpy as np
import matplotlib.pyplot as plt
import osipi

# %%
# Convert a series of R1 values to the corresponding signal intensities.

R1 = np.array([0.0, 1.5, 3.0, 4.0, 10.0]) # R1 in units of /s
k = np.float64(150.0) # constant of proportionality in units of arb. unit s
signal = osipi.R1_to_s_linear(R1, k) # signal in arb. unit
print(f'Signal: {signal}')

# Plot signal vs. R1
plt.plot(R1, signal, 'ro-')
plt.xlabel('R1 (/sec)')
plt.ylabel('signal (arb. unit)')
plt.show()
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
[project]
name = "osipi"
version = "0.1.2"
dependencies = [
"numpy",
dependencies = [
"numpy", "scipy"
]

# optional information

description = "The authorative python package for perfusion MRI"
readme = "README.md"
authors = [
{ name = "Luis Torres", email = "[email protected]" },
{ name = "Luis Torres", email = "[email protected]" },
{ name = "Steven Sourbron", email = "[email protected]" },
]
license = { file = "LICENSE" }
Expand Down Expand Up @@ -52,7 +52,7 @@ tests = [
docs = [
"sphinx",
"pydata-sphinx-theme",
"myst-parser",
"myst-parser",
"sphinx-copybutton",
"sphinx-design",
"sphinx-remove-toctrees",
Expand Down
6 changes: 5 additions & 1 deletion src/osipi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@
from ._tissue import (
tofts,
extended_tofts
)
)

from ._signal import (
R1_to_s_linear
)
27 changes: 27 additions & 0 deletions src/osipi/_signal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import numpy as np
from numpy.typing import NDArray


def R1_to_s_linear(R1: NDArray[np.float64], k: np.float64) -> NDArray[np.float64]:
"""Linear model for relationship between R1 and magnitude signal, s = k.R1
Args:
R1 (1D array of np.float64): vector of longitudinal relaxation rate in units of /s. [OSIPI code Q.EL1.001]
k (np.float64): proportionality constant in units of arb. unit s [OSIPI code Q.GE1.009]
Returns:
1D array of floats: vector of magnitude signal in arb. unit [OSIPI code Q.MS1.001]
References:
- Lexicon url: https://osipi.github.io/OSIPI_CAPLEX/perfusionModels/#LinModel_SM2
- Lexicon code: M.SM2.001
- OSIPI name: Linear model
- Adapted from equation given in the Lexicon
"""
# check R1 is a 1D array of floats
if not (isinstance(R1, np.ndarray) and R1.ndim == 1 and R1.dtype == np.float64):
raise TypeError("R1 must be a 1D NumPy array of np.float64")
# calculate signal
return k*R1


20 changes: 20 additions & 0 deletions tests/test_signal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import numpy as np
import osipi


def test_signal_R1_to_s_linear():

# 1. Simple use case
R1 = np.array([0.0, 1.5, 3.0, 4.0, 10.0]) # R1 in units of /s
k = np.float64(150.0) # constant of proportionality in units of arb. unit s
signal_truth = np.array([0.0, 225.0, 450.0, 600.0, 1500.0]) # expected signal in arb. unit
signal = osipi.R1_to_s_linear(R1, k) # estimated signal
np.testing.assert_allclose(signal_truth, signal, rtol=0, atol=1e-7)


if __name__ == "__main__":

test_signal_R1_to_s_linear()

print('All signal functionality tests passed!!')

0 comments on commit 48dff26

Please sign in to comment.