xcist / main

simulation and reconstruction package
BSD 3-Clause "New" or "Revised" License
45 stars 20 forks source link

3D helical fan-beam simulation #61

Closed xiaogengen-007 closed 5 months ago

xiaogengen-007 commented 7 months ago

Hi,

Thank you so much for making this incredible tool!

I would like to run a 3D helical fan-beam scan on a DICOM image (like that used in routine clinical CT). Is there any 3D fan-beam demo available? If not, could you kindly point to me where to start with?

I am also curious if I should specify the scanning protocol in the cfg files directly or if it might be better to directly use the DD3Proj function (from gecatsim.pyfiles.C_DD3Proj import DD3Proj) for the simulation.

Thanks!

zhangjy-ge commented 7 months ago

Hi,

The first step you would need to do is to convert DICOM image to density maps of different materials (such as water and bone). You can see an example of our voxelized phantom here: https://github.com/xcist/main/tree/master/gecatsim/phantom/CatSimLogo_1024. The density map of xxx_1024x1024x1.raw can be visualized using imagej.

If you want to do helical 3D fan-beam simulations with full physics models (noise, cross talk, etc), then you may want to check out example here: https://github.com/xcist/main/blob/master/gecatsim/examples/Sim_Sample.py, just change protocol.tableSpeed to a non-zero value to get helical scans. It is recommended to set parameters in cfg files.

Note that if you call DD3Proj directly (as in https://github.com/xcist/main/blob/master/gecatsim/examples/DD3Proj_Sample.py), you will not have noise etc, it is an ideal projector.

Let me know if you have more questions.

xiaogengen-007 commented 7 months ago

Hi zhangjy-ge,

Thank you for the quick response and it is really helpful.

I managed to convert 3D DICOM images to density maps and successfully ran a 3D axial cone-beam simulation and reconstruction. But I am still confused about how to run a helical fan-beam scan.

My major confusion lies in the key difference between a fan-beam vs a cone-beam scan in the scanner and protocol settings. Since I didn't find any parameters defining the beam shape, I am guessing that the fan vs cone beam setups are defined by the number of rows of detectors used and also the scattering model. Apart from that, should I modify the recon setting for the helical fan-beam scan?

I have attached my experiment settings and reconstruction results for reference. I used a 3D phantom with 10 slices (3mm slice thickness). The axial cone-beam experiment successfully reconstructed 10 slices, while the helical fan-beam experiment only reconstructed 1 slice. I'm listing the different parameters I used for my axial cone-beam vs helical fan-beam experiment. For the rest, I just used the default ones in examples/Sim_Sample.py (i.e. Scanner_Sample_generic.cfg and Protocol_Sample_axial.cfg).

Axial cone-beam experiment:

# scanner ct.scanner.detectorRowsPerMod = 64 ct.scanner.detectorRowCount = 64 # protocol nslc = 1 ct.protocol.viewsPerRotation = 200 ct.protocol.viewCount = ct.protocol.viewsPerRotation*nslc ct.protocol.startViewId = 0 ct.protocol.stopViewId = ct.protocol.viewCount-1 ct.protocol.tableSpeed = 0 ct.protocol.rotationTime = 1.0 ct.protocol.startZ = 0 # recon ct.recon.reconType = 'fdk_equiAngle' ct.recon.sliceCount = 10 ct.recon.sliceThickness = 3

Helical fan-beam experiment:

# scanner ct.scanner.detectorRowsPerMod = 16 ct.scanner.detectorRowCount = 16 # protocol nslc = 10 ct.protocol.viewsPerRotation = 200 ct.protocol.viewCount = ct.protocol.viewsPerRotation*nslc ct.protocol.startViewId = 0 ct.protocol.stopViewId = ct.protocol.viewCount-1 ct.protocol.tableSpeed = 3.0 ct.protocol.rotationTime = 1.0 ct.protocol.startZ = -15.0 # recon ct.recon.reconType = 'fdk_equiAngle' ct.recon.sliceCount = 10 ct.recon.sliceThickness = 3

Reconstruction results for cone-beam: image

Reconstruction results for fan-beam: Only the slice at offset -15 (ct.protocol.startZ) was reconstructed, other slices were missing. And I don't know why the images are flipped in both AP and LR directions. image

Thank you so much in advance!

zhangjy-ge commented 6 months ago

For fan-beam vs cone-beam, yes it is defined by number of detector rows (scattering model will take number of rows into account so you don't need to worry about it). And for helical scan, we should use recon.reconType = 'helical_equiAngle'. Probably this is the reason why you see weird results. Also recon.sliceThickness should not be too large otherwise you may see nothing for most slices.

Just a reminder, when you define phantoms, make sure you have enough length in the z direction, i.e., try to set z_size to a large enough number in you json file.

xiaogengen-007 commented 5 months ago

Thank you! That fixed my problem!