Skip to content

Commit

Permalink
Generate a variety of testing data and came up command_line version o…
Browse files Browse the repository at this point in the history
…f sim_vim_sig.py
  • Loading branch information
Unique-Usman committed Mar 5, 2024
1 parent f60f04f commit 3868cc1
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 983 deletions.
7 changes: 7 additions & 0 deletions phantoms/MR_XCAT_qMRI/b_values.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
[0.0, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 50.0, 75.0, 100.0, 150.0, 250.0, 350.0, 400.0, 550.0, 700.0, 850.0, 1000.0],
[0.0, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 50.0, 75.0, 100.0, 150.0, 250.0, 350.0, 400.0, 550.0, 700.0, 850.0, 1000.0, 1100.0, 1200.0],
[0.0, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 50.0, 75.0, 100.0, 150.0, 250.0, 350.0, 400.0, 500.0, 700.0, 800.0, 1000.0, 1100.0, 1200.0],
[0.0, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 50.0, 75.0, 100.0, 150.0, 250.0, 350.0, 450.0, 550.0, 675.0, 800.0],
[0.0, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 50.0, 75.0, 100.0, 150.0, 250.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0]
]
21 changes: 0 additions & 21 deletions phantoms/MR_XCAT_qMRI/b_values.py

This file was deleted.

179 changes: 115 additions & 64 deletions phantoms/MR_XCAT_qMRI/sim_ivim_sig.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from scipy.io import loadmat
import nibabel as nib
import json
import argparse
import os

##########
# code written by Oliver J Gurney-Champion
Expand Down Expand Up @@ -103,7 +105,7 @@ def contrast_curve_calc():
D[36] = 3e-3 # 36 artery
D[37] = 3e-3 # 37 vein
D[40] = 1.31e-3 # 40 asc lower intestine : Hai-Jing et al. doi: 10.1097/RCT.0000000000000926
D[41] = 1.31e-3 # 41 trans lower intestine : Hai-Jing et al. doi: 10.1097/RCT.0000000000000926
D[41] = 1.31e-3 # 41 trans lower# If conversion fails, try splitting the input as a lis intestine : Hai-Jing et al. doi: 10.1097/RCT.0000000000000926
D[42] = 1.31e-3 # 42 desc lower intestine : Hai-Jing et al. doi: 10.1097/RCT.0000000000000926
D[43] = 1.31e-3 # 43 small intestine : Hai-Jing et al. doi: 10.1097/RCT.0000000000000926
D[50] = 3e-3 # 50 pericardium
Expand Down Expand Up @@ -364,76 +366,125 @@ def XCAT_to_MR_DCE(XCAT, TR, TE, bvalue, D, f, Ds, b0=3, ivim_cont = True):
return MR, Dim, fim, Dpim, legend

if __name__ == '__main__':
bvalue = np.array([0., 1, 2, 5, 10, 20, 30, 50, 75, 100, 150, 250, 350, 400, 550, 700, 850, 1000])
noise = 0.0005
motion = False
interleaved = False
sig, XCAT, Dim, fim, Dpim, legend = phantom(bvalue, noise, motion=motion, interleaved=interleaved)
# sig = np.flip(sig,axis=0)
# sig = np.flip(sig,axis=1)
res=np.eye(4)
res[2]=2

voxel_selector_fraction = 0.5
D, f, Ds = contrast_curve_calc()
ignore = np.isnan(D)
generic_data = {}
for level, name in legend.items():
if len(ignore) > level and ignore[level]:
continue
selector = XCAT == level
voxels = sig[selector]
if len(voxels) < 1:
continue
signals = np.squeeze(voxels[int(voxels.shape[0] * voxel_selector_fraction)]).tolist()
generic_data[name] = {
'noise': noise,
'D': np.mean(Dim[selector], axis=0),
'f': np.mean(fim[selector], axis=0),
'Dp': np.mean(Dpim[selector], axis=0),
'data': signals
}
generic_data['config'] = {
'bvalues': bvalue.tolist()
}
with open('generic.json', 'w') as f:
json.dump(generic_data, f, indent=4)
parser = argparse.ArgumentParser(description=f"""
A commandline for generating a 4D IVIM phantom as nifti file
""")

def parse_bvalues_file(file_path):
"""Used for passing the JSON file"""
if not os.path.exists(file_path):
raise argparse.ArgumentTypeError(f"File '{file_path}' does not exist")

try:
with open(file_path, "r") as file:
bvalues_list = json.load(file)
if not isinstance(bvalues_list, list):
raise argparse.ArgumentTypeError("JSON file does not contain a list of b-values")
for bvalue in bvalues_list:
if not isinstance(bvalue, list):
raise argparse.ArgumentTypeError("bvalues in JSON file are not lists")
for v in bvalue:
if not isinstance(v, float):
raise argparse.ArgumentTypeError("Values in lists are not float")
except json.JSONDecodeError as e:
raise argparse.ArgumentTypeError(f"Invalid JSON file: {e}")

return bvalues_list


nifti_img = nib.Nifti1Image(sig, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
if not motion:
output_file = 'output.nii.gz' # Replace with your desired output file name
elif interleaved:
output_file = 'output_resp_int.nii.gz' # Replace with your desired output file name
parser.add_argument("-b", "--bvalue", type=float,
nargs="+",
help="B values (list of of numbers)")
parser.add_argument("-bf", "--bvalues-file", metavar="FILE", type=parse_bvalues_file,
help='JSON file containing the b-values')
parser.add_argument("-n", "--noise", type=float, default=0.0005, help="Noise")
parser.add_argument("-m", "--motion", action="store_true", help="Motion flag")
parser.add_argument("-i", "--interleaved", action="store_true", help="Interleaved flag")
args = parser.parse_args()

if args.bvalues_file and args.bvalue:
raise argparse.ArgumentError(None, "Arguments --bvalues-file and --bvalues are mutually exclusive")

bvalues = None
if args.bvalues_file:
bvalues = args.bvalues_file
elif args.bvalue:
bvalues = [args.bvalue]
else:
output_file = 'output_resp.nii.gz' # Replace with your desired output file name
bvalues = [[0., 1, 2, 5, 10, 20, 30, 50, 75, 100, 150, 250, 350, 400, 550, 700, 850, 1000]]

noise = args.noise
motion = args.motion
interleaved = args.interleaved

for index, bvalue in enumerate(bvalues):
bvalue = np.array(bvalue)
sig, XCAT, Dim, fim, Dpim, legend = phantom(bvalue, noise, motion=motion, interleaved=interleaved)
# sig = np.flip(sig,axis=0)
# sig = np.flip(sig,axis=1)
res=np.eye(4)
res[2]=2

voxel_selector_fraction = 0.5
D, f, Ds = contrast_curve_calc()
ignore = np.isnan(D)
generic_data = {}
for level, name in legend.items():
if len(ignore) > level and ignore[level]:
continue
selector = XCAT == level
voxels = sig[selector]
if len(voxels) < 1:
continue
signals = np.squeeze(voxels[int(voxels.shape[0] * voxel_selector_fraction)]).tolist()
generic_data[name] = {
'noise': noise,
'D': np.mean(Dim[selector], axis=0),
'f': np.mean(fim[selector], axis=0),
'Dp': np.mean(Dpim[selector], axis=0),
'data': signals
}
generic_data['config'] = {
'bvalues': bvalue.tolist()
}
with open(f'generic_{index}.json', 'w') as f:
json.dump(generic_data, f, indent=4)


nifti_img = nib.Nifti1Image(sig, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
if not motion:
output_file = f'output_{index}.nii.gz' # Replace with your desired output file name
elif interleaved:
output_file = f'output_resp_int_{index}.nii.gz' # Replace with your desired output file name
else:
output_file = f'output_resp_{index}.nii.gz' # Replace with your desired output file name

nib.save(nifti_img, output_file)
nib.save(nifti_img, output_file)


nifti_img = nib.Nifti1Image(XCAT, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
output_file = 'output_xcat.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)
nifti_img = nib.Nifti1Image(XCAT, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
output_file = f'output_xcat_{index}.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)

nifti_img = nib.Nifti1Image(Dim, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
output_file = 'D.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)
nifti_img = nib.Nifti1Image(Dim, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
output_file = f'D_{index}.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)

nifti_img = nib.Nifti1Image(fim, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
output_file = 'f.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)
nifti_img = nib.Nifti1Image(fim, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
output_file = f'f_{index}.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)

nifti_img = nib.Nifti1Image(Dpim, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
output_file = 'Dp.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)
nifti_img = nib.Nifti1Image(Dpim, affine=res) # Replace affine if necessary
# Save the NIfTI image to a file
nifti_img.header.set_data_dtype(np.float64)
output_file = f'Dp_{index}.nii.gz' # Replace with your desired output file name
nib.save(nifti_img, output_file)

np.savetxt('bvals.txt', bvalue)
np.savetxt(f'bvals_{index}.txt', bvalue)
Loading

0 comments on commit 3868cc1

Please sign in to comment.