-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Branchless distance-driven BProj and Proj working
- Loading branch information
0 parents
commit 3f9e6c0
Showing
16 changed files
with
2,573 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
pyDBT | ||
====== | ||
|
||
This repository is a python extension of the [DBT toolbox](https://github.com/LAVI-USP/DBT-Reconstruction) from LAVI-USP. | ||
|
||
|
||
|
||
## How to install? | ||
|
||
1. Download the toolbox or clone the directory: | ||
|
||
* ```git clone https://github.com/LAVI-USP/pyDBT.git``` | ||
|
||
2. Go to parent directory: | ||
|
||
* ```cd pyDBT``` | ||
|
||
3. Install the package: | ||
|
||
* ```python3 setup.py install``` | ||
|
||
4. run the example: | ||
|
||
* ```cd pydbt && python3 example.py``` | ||
|
||
5. The toolbox was tested on **Linux** (Ubuntu) x64, and **MacoS** Catalina machines, with python **3.7.5**. | ||
|
||
6. You can also run the [MATLAB version](https://github.com/LAVI-USP/DBT-Reconstruction) of the toolbox. | ||
|
||
** Please report issues [here](https://github.com/LAVI-USP/pyDBT/issues). ** | ||
|
||
## Contribute? | ||
|
||
We are pleased with any contributions. Fell free to make any [pull requests](https://github.com/LAVI-USP/pyDBT/pulls) or send us an e-mail. | ||
|
||
|
||
## Toolbox manual: | ||
|
||
You can find the [manual](https://github.com/LAVI-USP/DBT-Reconstruction/wiki/Toolbox-Manual) from the MATLAB version, which is pretty much the same. I will create a specific one for the python version in the future. | ||
|
||
## Contact: | ||
|
||
If you have any question or suggestion, please send us an e-mail: | ||
|
||
- Rodrigo - rodrigo dot vimieiro at gmail dot com | ||
- Marcelo - mvieira at sc dot usp dot br | ||
|
||
## License: | ||
|
||
The toolbox is licensed under the **GNU General Public License v3.0**. Please check the [licence file](https://github.com/LAVI-USP/pyDBT/blob/master/LICENSE). | ||
|
||
## Reference: | ||
|
||
If you use the toolbox, we will be very grateful if you refer to this [paper](https://doi.org/10.1007/978-981-13-2517-5_53): | ||
|
||
> Vimieiro R.B., Borges L.R., Vieira M.A.C. (2019) Open-Source Reconstruction Toolbox for Digital Breast Tomosynthesis. In: Costa-Felix R., Machado J., Alvarenga A. (eds) XXVI Brazilian Congress on Biomedical Engineering. IFMBE Proceedings, vol 70/2. Springer, Singapore. | ||
## Citations: | ||
|
||
You can find [here](https://scholar.google.com.br/scholar?oi=bibs&hl=pt-BR&cites=3156269064066227282) the papers that have used the toolbox. | ||
|
||
## Acknowledgments: | ||
|
||
This work was supported by the São Paulo Research Foundation ([FAPESP](http://www.fapesp.br/) grant 2016/25750-0) and by the National Council for Scientific and Technological Development ([CNPq](http://www.cnpq.br/)). Nobody does anything alone, so we would like to thank the contribution of our lab members and the [Barretos Love Hospital](https://www.hcancerbarretos.com.br) for providing the images of DBT. | ||
|
||
--- | ||
|
||
Laboratory of Computer Vision ([Lavi](http://iris.sel.eesc.usp.br/lavi/)) | ||
Department of Electrical and Computer Engineering | ||
São Carlos School of Engineering, University of São Paulo | ||
São Carlos - Brazil |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Tue Jan 14 08:37:11 2020 | ||
@author: Rodrigo | ||
""" | ||
|
||
#%% | ||
import matplotlib.pyplot as plt | ||
|
||
from parameterSettings import geometry_settings | ||
from functions.manageDicom import readDicom | ||
from functions.dataPreProcess import dataPreProcess | ||
from functions.projectionDDb import projectionDDb | ||
from functions.backprojectionDDb import backprojectionDDb | ||
from functions.initialConfig import initialConfig | ||
|
||
#%% Call function for initial configurations | ||
|
||
libFiles = initialConfig() | ||
|
||
#%% Create a DBT geometry | ||
|
||
geo = geometry_settings() | ||
geo.GE() | ||
|
||
#%% Get DICOM data | ||
|
||
dcmPath = "/home/rodrigo/Downloads/imgs/" | ||
proj = readDicom(dcmPath,geo) | ||
|
||
proj = dataPreProcess(proj, geo) | ||
|
||
#%% | ||
|
||
print("Starting reconstruction...") | ||
|
||
vol = backprojectionDDb(proj, geo, libFiles) | ||
plt.figure() | ||
plt.title('Reconstructed slice') | ||
plt.imshow(vol[:,:,50] , cmap=plt.get_cmap('gist_gray')) | ||
|
||
print("Starting projection...") | ||
|
||
proj = projectionDDb(vol, geo, libFiles) | ||
plt.figure() | ||
plt.title('Projected volume') | ||
plt.imshow(proj[:,:,4] , cmap=plt.get_cmap('gist_gray')) | ||
|
||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Fri Jan 17 18:46:40 2020 | ||
@author: Rodrigo | ||
""" | ||
|
||
import numpy as np | ||
import numpy.ctypeslib as ctl | ||
|
||
from functions.utilities import findAndLoadLibray | ||
from functions.utilities import geoAsNp | ||
|
||
def backprojectionDDb(proj, geo, libFiles): | ||
|
||
|
||
# Check if the input is in proper size | ||
if not (proj.shape[0] == geo.nv and proj.shape[1] == geo.nu and proj.shape[2] == geo.nProj): | ||
raise ValueError('First argument needs to have the same number of rows, cols and slices as in the configuration file.') | ||
|
||
|
||
# Find and library | ||
lib = findAndLoadLibray(libFiles, 'backprojectionDDb') | ||
|
||
|
||
backprojectionDDb_lib = lib.backprojectionDDb_lib | ||
|
||
backprojectionDDb_lib.argtypes = [ctl.ndpointer(np.float64, flags='aligned, c_contiguous'), | ||
ctl.ndpointer(np.float64, flags='aligned, c_contiguous'), | ||
ctl.ndpointer(np.float32, flags='aligned, c_contiguous')] | ||
|
||
|
||
# Transform geo class in numpy array | ||
geoNp = geoAsNp(geo) | ||
|
||
|
||
vol_transp = np.empty([geo.nz, geo.nx, geo.ny], dtype=np.float64) | ||
|
||
proj_transp = np.transpose(proj, (2, 1, 0)).copy() | ||
|
||
backprojectionDDb_lib (proj_transp, vol_transp, geoNp) | ||
|
||
vol = np.transpose(vol_transp, (2, 1, 0)).copy() | ||
|
||
|
||
return vol | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Tue Oct 22 10:34:24 2019 | ||
@author: rodrigo | ||
""" | ||
|
||
import numpy as np | ||
|
||
def dataPreProcess(proj, geo): | ||
|
||
proj = cropProj(proj) | ||
|
||
proj = transfIntensity(proj) | ||
|
||
# Modifies parameters based on segmentation | ||
geo.nu = proj.shape[1] # Number of pixels (columns) | ||
|
||
return proj | ||
|
||
|
||
|
||
def cropProj(proj): | ||
|
||
Gap = 20; | ||
|
||
maxValue = np.max(proj) | ||
|
||
vertProj = np.sum(maxValue-proj[:,:,proj.shape[2]//2 - 1], axis=0) # Horizontal Profile | ||
|
||
Ind = np.argmax(np.diff(vertProj[10:])) - Gap # Smooth the signal and takes its max positive derivative | ||
|
||
proj_crop = proj[:,Ind:,:] | ||
|
||
return proj_crop | ||
|
||
|
||
def transfIntensity(proj): | ||
|
||
# Transform intensity image in attenuation coefficients | ||
proj = -np.log(proj/np.max(proj)); | ||
|
||
return proj | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Wed Jan 22 13:35:00 2020 | ||
@author: rodrigo | ||
""" | ||
|
||
import pathlib | ||
|
||
def initialConfig(): | ||
|
||
workDir = pathlib.Path().absolute() | ||
|
||
outDir = workDir / 'output' | ||
|
||
if not(outDir.exists() and outDir.is_dir()): | ||
pathlib.Path(outDir).mkdir() | ||
|
||
libFiles = findLibraries(workDir) | ||
|
||
return libFiles | ||
|
||
|
||
def findLibraries(workDir): | ||
|
||
buildDir = workDir / '../build' | ||
|
||
if not(buildDir.exists() and buildDir.is_dir()): | ||
raise ValueError('Cannot find the build folder. Make sure to run the setup.py or follow the instructions on the package Github.') | ||
|
||
libDir = [] | ||
|
||
# Find libray directory | ||
for f in buildDir.iterdir(): | ||
if f.is_dir(): | ||
if 'lib.' in str(f): | ||
libDir = f | ||
|
||
# Test if libDir is empty | ||
if not libDir: | ||
raise ValueError('Cannot find the lib folder. Make sure to run the setup.py or follow the instructions on the package Github.') | ||
|
||
libFiles = [] | ||
|
||
# Find all .so files | ||
for libFile in pathlib.Path(libDir).glob('*.so'): | ||
libFiles.append((str(libDir),str(libFile).split('/')[-1])) | ||
|
||
|
||
return libFiles | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Tue Oct 8 08:39:59 2019 | ||
@author: rodrigo | ||
""" | ||
|
||
import pydicom | ||
import numpy as np | ||
from os import walk | ||
|
||
def readDicom(path, geo): | ||
|
||
dcmFiles = [] | ||
for (_, _, filenames) in walk(path): | ||
for file in filenames: | ||
if file.endswith(".dcm"): | ||
dcmFiles.append(file) | ||
break | ||
|
||
# Test if list is empty | ||
if not dcmFiles: | ||
raise ValueError('No DICOM files found in the specified path.') | ||
|
||
proj = np.zeros([geo.nv,geo.nu,geo.nProj],dtype='uint16') | ||
|
||
|
||
for f in dcmFiles: | ||
nProj = int(f.split('.')[0]) | ||
proj_dcmH = pydicom.dcmread(path + f) | ||
proj[:,:,nProj] = proj_dcmH.pixel_array | ||
|
||
return proj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Created on Fri Jan 17 13:36:50 2020 | ||
@author: Rodrigo | ||
""" | ||
|
||
import numpy as np | ||
import numpy.ctypeslib as ctl | ||
|
||
from functions.utilities import findAndLoadLibray | ||
from functions.utilities import geoAsNp | ||
|
||
def projectionDDb(vol, geo, libFiles): | ||
|
||
|
||
# Check if the input is in proper size | ||
if not (vol.shape[0] == geo.ny and vol.shape[1] == geo.nx and vol.shape[2] == geo.nz): | ||
raise ValueError('First argument needs to have the same number of rows, cols and slices as in the configuration file.') | ||
|
||
|
||
# Find and library | ||
lib = findAndLoadLibray(libFiles, 'projectionDDb') | ||
|
||
|
||
projectionDDb_lib = lib.projectionDDb_lib | ||
|
||
projectionDDb_lib.argtypes = [ctl.ndpointer(np.float64, flags='aligned, c_contiguous'), | ||
ctl.ndpointer(np.float64, flags='aligned, c_contiguous'), | ||
ctl.ndpointer(np.float32, flags='aligned, c_contiguous')] | ||
|
||
|
||
# Transform geo class in numpy array | ||
geoNp = geoAsNp(geo) | ||
|
||
|
||
proj_transp = np.empty([geo.nProj, geo.nu, geo.nv], dtype=np.float64) | ||
|
||
vol_transp = np.transpose(vol, (2, 1, 0)).copy() | ||
|
||
projectionDDb_lib (vol_transp, proj_transp, geoNp) | ||
|
||
proj = np.transpose(proj_transp, (2, 1, 0)).copy() | ||
|
||
|
||
return proj | ||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.