dhavalkadia-fda
commited on
Commit
•
d0f9f3b
1
Parent(s):
26438a8
Upload 30 files
Browse files- PyBDC/.readthedocs.yaml +18 -0
- PyBDC/CT_Dose_Calculate_Quick_Guide.txt +56 -0
- PyBDC/Doc/GUI_Example_PyBDC.PNG +0 -0
- PyBDC/Doc/Makefile +20 -0
- PyBDC/Doc/conf.py +25 -0
- PyBDC/Doc/gui.rst +37 -0
- PyBDC/Doc/index.rst +73 -0
- PyBDC/Doc/install.rst +33 -0
- PyBDC/Doc/make.bat +35 -0
- PyBDC/Doc/methods.rst +130 -0
- PyBDC/Doc/requirements.txt +2 -0
- PyBDC/Dosage_Test_Case_spectrum_55kVp2mmAl.xlsx +0 -0
- PyBDC/License +29 -0
- PyBDC/Paper citations.txt +13 -0
- PyBDC/PyBDC.py +859 -0
- PyBDC/README.md +56 -0
- PyBDC/User_Guide.md +57 -0
- PyBDC/Verification.py +168 -0
- PyBDC/dose_equations.py +68 -0
- PyBDC/dose_table/Hernandez_heterogeneous_dgn.txt +63 -0
- PyBDC/dose_table/Sarno_mono_dgn.txt +122 -0
- PyBDC/dose_table/Sarno_poly_dgn.txt +91 -0
- PyBDC/dose_table/Sechopoulos_dgn.txt +15 -0
- PyBDC/incident_spectrum/49kVp_1.5_Al.txt +40 -0
- PyBDC/incident_spectrum/55kVp1and5mmAl.txt +110 -0
- PyBDC/incident_spectrum/60kV_0.2_Cu.txt +51 -0
- PyBDC/incident_spectrum/spectrum_45kVp_1mm.txt +71 -0
- PyBDC/incident_spectrum/spectrum_55kVp2mmAl.txt +91 -0
- PyBDC/method_specific_inputs.toml +30 -0
- PyBDC/requirements.txt +5 -0
PyBDC/.readthedocs.yaml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# .readthedocs.yaml
|
2 |
+
# Read the Docs configuration file
|
3 |
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
4 |
+
|
5 |
+
# Required
|
6 |
+
version: 2
|
7 |
+
|
8 |
+
# Set the version of Python and other tools you might need
|
9 |
+
build:
|
10 |
+
os: ubuntu-22.04
|
11 |
+
tools:
|
12 |
+
python: "3.10"
|
13 |
+
# You can also specify other tool versions:
|
14 |
+
# nodejs: "19"
|
15 |
+
# rust: "1.64"
|
16 |
+
# golang: "1.19"
|
17 |
+
|
18 |
+
|
PyBDC/CT_Dose_Calculate_Quick_Guide.txt
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Quick Start Guide
|
2 |
+
|
3 |
+
1. To begin start by choosing a method: Sarno Koning, Sarno Incident Spectrum, or Hernandez Heterogeneous BCT
|
4 |
+
|
5 |
+
a) Each method can be selected by selecting the radio button next to the method
|
6 |
+
|
7 |
+
i) the default is Sarno Incident Spectrum
|
8 |
+
|
9 |
+
c) Selecting the Sarno Koning BCT will lead to an output in the text box stating a description of Koning
|
10 |
+
BCT apparatus
|
11 |
+
|
12 |
+
b) Selecting the Hernandez Heterogeneous BCT method will lead to the text box on the bottom corner being
|
13 |
+
filled with the a description for each of the heterogeneous categories
|
14 |
+
|
15 |
+
2. After selecting a method, choose your parameters in the box next over
|
16 |
+
|
17 |
+
a) Sample parameters include breast diameter, breast height, etc.
|
18 |
+
|
19 |
+
b) Simply click on the downward arrow and choose the parameter of your choice
|
20 |
+
|
21 |
+
c) You'll notice some parameters are deactivated and this is due to the method of your choice. Each method
|
22 |
+
uses different sets of parameters. As such, the parameters necessary for the method will remain active
|
23 |
+
and those not necessary will remain inactive
|
24 |
+
|
25 |
+
3. After choosing parameters, enter your air KERMA along with the input units and the desired output units.
|
26 |
+
|
27 |
+
a) Simply enter your air KERMA into the air KERMA box and like before choose the input units in Air KERMA
|
28 |
+
Units and output units via MGD Units by pressing the downward arrow
|
29 |
+
|
30 |
+
4. Depending on the method of your choice, you will have the option to input an incident spectrum and graph that
|
31 |
+
spectrum
|
32 |
+
|
33 |
+
a) If you have chosen either Sarno Incident Spectrum or Hernandez Heterogeneous BCT, the option the input an
|
34 |
+
incident spectrum will be available to you.
|
35 |
+
|
36 |
+
i) This is not optional; you must enter an incident spectrum for the method to work
|
37 |
+
|
38 |
+
b) Simply press the Input Incident Spectrum Button and a popup will appear prompting you to choose a file.
|
39 |
+
Please select an appropriate text file following the format outlined in the complete user guide.
|
40 |
+
|
41 |
+
i) Once an acceptable file has been chosen, a shortened file name will appear in the text box found on
|
42 |
+
the bottom left
|
43 |
+
|
44 |
+
c) After inputting the file, the Graph Spectrum button will activate. You can then press the Graph Spectrum
|
45 |
+
button which will display your incident spectrum on the graph
|
46 |
+
|
47 |
+
5. Once you are satisfied with all your inputs, you can press the Calculate Dose button found at the bottom left corner
|
48 |
+
next to the Clear Text button
|
49 |
+
|
50 |
+
a) Pressing the Calculate Dose button will lead to an output in the text box of your mean glandular dose value
|
51 |
+
and your chosen parameters.
|
52 |
+
|
53 |
+
b) The text will remain in the box unless you elect to clear the box. The box can be easily cleared by pressing
|
54 |
+
the Clear Text button. Do note that your previous values will be cleared and cannot be retrieved.
|
55 |
+
|
56 |
+
6. For a complete user guide refer to the user guide
|
PyBDC/Doc/GUI_Example_PyBDC.PNG
ADDED
PyBDC/Doc/Makefile
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Minimal makefile for Sphinx documentation
|
2 |
+
#
|
3 |
+
|
4 |
+
# You can set these variables from the command line, and also
|
5 |
+
# from the environment for the first two.
|
6 |
+
SPHINXOPTS ?=
|
7 |
+
SPHINXBUILD ?= sphinx-build
|
8 |
+
SOURCEDIR = source
|
9 |
+
BUILDDIR = build
|
10 |
+
|
11 |
+
# Put it first so that "make" without argument is like "make help".
|
12 |
+
help:
|
13 |
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
14 |
+
|
15 |
+
.PHONY: help Makefile
|
16 |
+
|
17 |
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
18 |
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
19 |
+
%: Makefile
|
20 |
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
PyBDC/Doc/conf.py
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Configuration file for the Sphinx documentation builder.
|
2 |
+
|
3 |
+
# -- Project information
|
4 |
+
project = 'PyBDC'
|
5 |
+
copyright = '2023, Marupudi'
|
6 |
+
author = 'Harsha Marupudi'
|
7 |
+
release = '0.1'
|
8 |
+
version = '0.1.0'
|
9 |
+
|
10 |
+
# -- General configuration
|
11 |
+
extensions = [
|
12 |
+
'sphinx.ext.duration',
|
13 |
+
'sphinx.ext.doctest',
|
14 |
+
'sphinx.ext.autodoc',
|
15 |
+
'sphinx.ext.autosummary',
|
16 |
+
'sphinx.ext.intersphinx',
|
17 |
+
]
|
18 |
+
|
19 |
+
intersphinx_mapping = {
|
20 |
+
'python': ('https://docs.python.org/3/', None),
|
21 |
+
'sphinx': ('https://www.sphinx-doc.org/en/master/', None),
|
22 |
+
}
|
23 |
+
intersphinx_disabled_domains = ['std']
|
24 |
+
|
25 |
+
templates_path = ['_templates']
|
PyBDC/Doc/gui.rst
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
GUI Overview
|
2 |
+
============
|
3 |
+
|
4 |
+
The Python GUI runs on Windows, Mac, and Linux. All inputs and buttons are shown in the screenshots of the interface below.
|
5 |
+
|
6 |
+
|
7 |
+
.. image:: GUI_Example_PyBDC.PNG
|
8 |
+
|
9 |
+
|
10 |
+
Figure 1: Screen captures of PyBDC program. The image shows example inputs used by the GUI to compute the mean glandular dose. The provided example is for the Sarno method with an incident spectrum measured at 55 kVp, with 2 mm of aluminum filtration. The incident spectrum is also plotted in the figure.
|
11 |
+
|
12 |
+
Data Files
|
13 |
+
==========
|
14 |
+
The program requires several data files found within the program directory. These data files consist of the dose tables necessary for dose calculations and a python file to read the text files and convert them to a pandas data frame which can be easily accessed. The following are the necessary data files:
|
15 |
+
|
16 |
+
Dose tables:
|
17 |
+
|
18 |
+
* Hernandez_heterogeneous_dgn
|
19 |
+
|
20 |
+
* Sarno_mono_dgn
|
21 |
+
|
22 |
+
* Sarno_poly_dgn
|
23 |
+
|
24 |
+
* Sechopoulos_dgn
|
25 |
+
|
26 |
+
The Hernandez heterogeneous text file contains columns for the photon energy values, and the different volume glandular fractions (V1, V3, and V5). The coefficients range are in units of mGy/mGy and range from 9 to 70 keV with a step size of 1.
|
27 |
+
|
28 |
+
The Sarno monoergentic DgN text file contains columns for the different breast diameters, the glandularity, and the breast height value. The DgN coefficients are in units of mGy/mGy. Lastly, the Sarno polyenergetic DgN text file contains columns for the HVL lengths, the different breast diameters, the glandularity, and the breast heights.
|
29 |
+
|
30 |
+
The Sechopoulos DgN text file contains a column for the breast diameter, breast length, and the different glandularities. The coefficients are in units of mGy/mGy.
|
31 |
+
|
32 |
+
Python file for dose equations:
|
33 |
+
dose_equations.py
|
34 |
+
|
35 |
+
This file simply reads the different tables mentioned above and converts them into a pandas data frame. The file further contains the necessary equations for calculating mean glandular dose values.
|
36 |
+
|
37 |
+
|
PyBDC/Doc/index.rst
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Welcome to PyBDC Documentation!
|
2 |
+
=====================================
|
3 |
+
|
4 |
+
Python toolkit for calculating dosage for breast CT.\
|
5 |
+
The following software enables accurate dose estimation for one or various breast exposures specifically for breast CT. The software can be used on Windows and Mac operating systems and using a graphical user interface. The mode is further explained below along with an overview of the methods, how to choose a method, the program inputs and buttons, the incident spectrum format, images of the GUI, and the accompanying data files.
|
6 |
+
|
7 |
+
|
8 |
+
Table of Contents
|
9 |
+
==================
|
10 |
+
.. toctree::
|
11 |
+
:hidden:
|
12 |
+
|
13 |
+
Home <self>
|
14 |
+
|
15 |
+
.. toctree::
|
16 |
+
:maxdepth: 2
|
17 |
+
|
18 |
+
install
|
19 |
+
methods
|
20 |
+
gui
|
21 |
+
|
22 |
+
examples
|
23 |
+
|
24 |
+
Methods Overview
|
25 |
+
==================
|
26 |
+
|
27 |
+
Currently supports the following plugins:
|
28 |
+
|
29 |
+
* Sarno Any Spectrum
|
30 |
+
* Hernandez Any Spectrum
|
31 |
+
* Sarno 49 kVp W Spectra
|
32 |
+
* Sechopoulus 49 kvP W Spectra
|
33 |
+
|
34 |
+
Detailed descriptions on individual methods are provided in section :ref:`Methods Overview`.
|
35 |
+
|
36 |
+
Installation
|
37 |
+
==================
|
38 |
+
**Clone PyBDC repository**
|
39 |
+
|
40 |
+
git clone https://github.com/harshamarupudi56/PyBDC.git
|
41 |
+
|
42 |
+
**Run the following commands to install required dependencies**
|
43 |
+
|
44 |
+
apt-get -y install python3.11-tk
|
45 |
+
apt-get -y install pip
|
46 |
+
cd PyBDC
|
47 |
+
pip install -r requirements.txt
|
48 |
+
|
49 |
+
**The required dependencies located in requirements.txt**
|
50 |
+
|
51 |
+
customtkinter==5.2.2
|
52 |
+
|
53 |
+
matplotlib==3.8.0
|
54 |
+
|
55 |
+
numpy==1.26.0
|
56 |
+
|
57 |
+
pandas==1.3.4
|
58 |
+
|
59 |
+
**Run PyBDC**
|
60 |
+
|
61 |
+
python3 PyBDC.py
|
62 |
+
|
63 |
+
|
64 |
+
**PyBDC Team:**
|
65 |
+
Harsha Marupudi, Jospeh Manus, Bahaa Ghammraoui
|
66 |
+
|
67 |
+
**Citations:**
|
68 |
+
|
69 |
+
Sarno, A., Mettivier, G., Di Lillo, F., & Russo, P. (2017). A Monte Carlo study of monoenergetic and polyenergetic normalized glandular dose (DgN) coefficients in mammography. Physics in medicine and biology, 62(1), 306–325. https://doi.org/10.1088/1361-6560/62/1/306
|
70 |
+
|
71 |
+
Hernandez, A. M., Becker, A. E., & Boone, J. M. (2019). Updated breast CT dose coefficients (DgNCT ) using patient-derived breast shapes and heterogeneous fibroglandular distributions. Medical physics, 46(3), 1455–1466. https://doi.org/10.1002/mp.13391
|
72 |
+
|
73 |
+
Sechopoulos, I., Feng, S. S., & D'Orsi, C. J. (2010). Dosimetric characterization of a dedicated breast computed tomography clinical prototype. Medical physics, 37(8), 4110–4120. https://doi.org/10.1118/1.3457331
|
PyBDC/Doc/install.rst
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Installation
|
2 |
+
==================
|
3 |
+
**Clone PyBDC repository**
|
4 |
+
|
5 |
+
.. code-block:: shell
|
6 |
+
|
7 |
+
git clone https://github.com/DIDSR/PyBDC.git
|
8 |
+
|
9 |
+
**Run the following commands to install required dependencies**
|
10 |
+
|
11 |
+
.. code-block:: shell
|
12 |
+
|
13 |
+
apt-get -y install python3.11-tk
|
14 |
+
apt-get -y install pip
|
15 |
+
cd PyBDC
|
16 |
+
pip install -r requirements.txt
|
17 |
+
|
18 |
+
**The required dependencies located in requirements.txt**
|
19 |
+
|
20 |
+
* customtkinter==5.2.2
|
21 |
+
|
22 |
+
* matplotlib==3.8.0
|
23 |
+
|
24 |
+
* numpy==1.26.0
|
25 |
+
|
26 |
+
* pandas==1.3.4
|
27 |
+
|
28 |
+
|
29 |
+
**Run PyBDC**
|
30 |
+
|
31 |
+
.. code-block:: shell
|
32 |
+
|
33 |
+
python3 PyBDC.py
|
PyBDC/Doc/make.bat
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@ECHO OFF
|
2 |
+
|
3 |
+
pushd %~dp0
|
4 |
+
|
5 |
+
REM Command file for Sphinx documentation
|
6 |
+
|
7 |
+
if "%SPHINXBUILD%" == "" (
|
8 |
+
set SPHINXBUILD=sphinx-build
|
9 |
+
)
|
10 |
+
set SOURCEDIR=source
|
11 |
+
set BUILDDIR=build
|
12 |
+
|
13 |
+
if "%1" == "" goto help
|
14 |
+
|
15 |
+
%SPHINXBUILD% >NUL 2>NUL
|
16 |
+
if errorlevel 9009 (
|
17 |
+
echo.
|
18 |
+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
19 |
+
echo.installed, then set the SPHINXBUILD environment variable to point
|
20 |
+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
21 |
+
echo.may add the Sphinx directory to PATH.
|
22 |
+
echo.
|
23 |
+
echo.If you don't have Sphinx installed, grab it from
|
24 |
+
echo.http://sphinx-doc.org/
|
25 |
+
exit /b 1
|
26 |
+
)
|
27 |
+
|
28 |
+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
29 |
+
goto end
|
30 |
+
|
31 |
+
:help
|
32 |
+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
33 |
+
|
34 |
+
:end
|
35 |
+
popd
|
PyBDC/Doc/methods.rst
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Methods Overview
|
2 |
+
==================
|
3 |
+
|
4 |
+
There are 4 methods available in PyBCD:
|
5 |
+
|
6 |
+
* Sarno 49 kVp W Spectra (Sarno Koning BCT)
|
7 |
+
|
8 |
+
* Sechopoulos 49 kVp Any Spectra (Sechopoulos Koning BCT)
|
9 |
+
|
10 |
+
* Sarno Any Specturm
|
11 |
+
|
12 |
+
* Hernandez Any Spectrum (Hernandez Heterogeneous BCT)
|
13 |
+
|
14 |
+
|
15 |
+
The Sarno Koning BCT method utilizes the Koning BCT apparatus which houses a 49 kVp W-anode with 1.40 mm Al. Other values are included because of possible variations in Al filter length. Sarno Any Spectrum on the other hand makes use of an incident X-ray spectrum input by the user. The Sarno model represents the breast as a cylinder with a homogoneous mixture of glandular and adipose tisssue. Additonally the model assumes a 1.45 mm thick skin layer and a radiation source placed 650 mm from the isocenter.
|
16 |
+
|
17 |
+
Sechopolous method also uses the Koning BCT apparatus. However, the method uses a single HVL value of 1.32 mm Al and models the breast as a semi-ellipsoid with a homogeneous mixture of adipose and glandular tissue.
|
18 |
+
|
19 |
+
The Hernandez Heterogeneous BCT method compared to the Sarno methods, models the breast as a heterogeneous mixture of adipose and glandular tissue where the individual tissues voxels are either 100% adipose or 100% glandular. The skin thickness is assumed to be 1.5 mm and the radiation source is placed 650 mm from the isocenter. Rather than being characterized by breast glandularity, this method uses volume glandular fraction or VGF for short. The heterogeneous categories, V1, V3, and V5 are characterized as follows:
|
20 |
+
|
21 |
+
V1: Volume Glandular Fraction (VGF) = 19.9%, median volume of 276 cm3, median diameter through the center of 87 mm, and median diameter at the chest wall of 103.4 mm
|
22 |
+
|
23 |
+
V3: Volume Glandular Fraction (VGF) = 9.5%, median volume of 616 cm3, median diameter through the center of 106.6 mm, and median diameter at the chest wall of 125.2 mm
|
24 |
+
|
25 |
+
V5: Volume Glandular Fraction (VGF) = 3.8%, median volume of 1174 cm3, median diameter through the center of 124.4 mm, and median diameter at the chest wall of 150.4 mm
|
26 |
+
|
27 |
+
|
28 |
+
Choosing a Method
|
29 |
+
==================
|
30 |
+
The GUI offers three methods the user can choose from which are Sarno Koning BCT, Sarno Incident Spectrum, and Hernandez Heterogeneous BCT via radio button selection. Next to each method, a radio button can be found that if pressed selects the method. You will note that once pressed, certain buttons and parameters are activated, and others are deactivated. What is activated and deactivated is as follows:
|
31 |
+
|
32 |
+
Sarno 49 kVp W Spectra (Sarno Koning BCT)
|
33 |
+
|
34 |
+
* Activated: Breast Diameter, Breast Height, Breast Glandularity, HVL, Air Kerma, Air Kerma units, MGD units, Clear Text, and Calculate Dose
|
35 |
+
|
36 |
+
* Deactivated: Heterogeneous Categories, Input Incident Spectrum, and Graph Spectrum
|
37 |
+
|
38 |
+
* Assumptions: Cylindrical breats of homogenous composition. Skin layer of 1.45 cm. 65 cm radiation source to isocenter distance.
|
39 |
+
|
40 |
+
Sechopoulos 49 kVp Any Spectra (Sechopoulos Koning BCT)
|
41 |
+
|
42 |
+
* Activated: Breast Diameter, Breast Height, Breast Glandularity, HVL, Air Kerma, Air Kerma units, MGD units, Clear Text, and Calculate Dose
|
43 |
+
|
44 |
+
* Deactivated: Heterogeneous Categories, Input Incident Spectrum, and Graph Spectrum
|
45 |
+
|
46 |
+
* Assumptions: Semi-ellipsoidal breast of homogeneous composition. Skin layer of 1.45 mm. 65 cm radiation source to isocenter distance.
|
47 |
+
|
48 |
+
Sarno Any Specturm
|
49 |
+
|
50 |
+
* Activated: Breast Diameter, Breast Height, Breast Glandularity, Air Kerma, Air Kerma units, MGD units, Input Incident Spectrum, Graph Spectrum*, Clear Text, and Calculate Dose
|
51 |
+
|
52 |
+
* Deactivated: HVL, Heterogeneous Categories
|
53 |
+
|
54 |
+
* Assumptions: Cylindircal brast of homogenous compositon. 65 cm radiatoin source to isocenter distance.
|
55 |
+
|
56 |
+
Hernandez Any Spectrum (Hernandez Heterogeneous BCT)
|
57 |
+
|
58 |
+
* Activated: Heterogeneous Categories, Air Kerma, Air Kerma units, MGD units, Input Incident Spectrum, Graph Spectrum, Clear Text, and Calculate Dose
|
59 |
+
|
60 |
+
* Deactivated: Breast Diameter, Breast Height, Breast Glandularity, HVL
|
61 |
+
|
62 |
+
* Assumptions: Real CT breast images were grouped into three volume glandular fraction categories V1, V2, and V3. Each category of breast assumes a heterogeneous composition. Skin layer of 1.50 mm. 65 cm radiation source to isocenter distance
|
63 |
+
|
64 |
+
Graph spectrum will be activated after a valid text file is entered. If an invalid text file is entered, a popup will appear prompting you to make the necessary changes.
|
65 |
+
Program Inputs and Buttons
|
66 |
+
|
67 |
+
|
68 |
+
Program Inputs and Buttons
|
69 |
+
==========================
|
70 |
+
Table 1 shows summarizes all the inputs into the program, the format, and the valid ranges. For the program inputs, the parameters other than BCT methods and the Air Kerma can be chosen using the downward arrow button. After clicking the downward arrow, a dropdown menu will appear where you can choose the option of your choice. The BCT method can be chosen via the radio buttons found to the left of the button and the Air Kerma can be manually entered in the box to the right of the parameter. Table 2 summarizes the different buttons and their purpose. These buttons can be simply pressed and the outlined effect in the table will occur. As mentioned above, in the Choosing a Method section, certain buttons will be active and inactive depending on the method chosen.
|
71 |
+
|
72 |
+
+---------------------------+-----------------------------------------------------+
|
73 |
+
| Parameter name | Input |
|
74 |
+
+===========================+=====================================================+
|
75 |
+
| BCT methods | Sarno Koning BCT |
|
76 |
+
| | Sarno Incident Spectrum |
|
77 |
+
| | Hernandez Heterogeneous BCT |
|
78 |
+
+---------------------------+-----------------------------------------------------+
|
79 |
+
| Breast Diameter (cm) | 8, 10, 12, 14, 16, 18 (Sarno method) |
|
80 |
+
| | 10, 12, 14, 16, 18 (Sechopoulos method) |
|
81 |
+
+---------------------------+-----------------------------------------------------+
|
82 |
+
| Breast Height | 1 x radius |
|
83 |
+
| | 1.5 x radius |
|
84 |
+
| | 2 x radius |
|
85 |
+
+---------------------------+-----------------------------------------------------+
|
86 |
+
| Breast Glandularity | 0.1%, 14.3%, 25%, 50%, 100% (Sarno method) |
|
87 |
+
| | 1%, 14.3%, 25%, 50%, 100% (Sechopoulos method) |
|
88 |
+
+---------------------------+-----------------------------------------------------+
|
89 |
+
| HVL (mm Al) | 1.25, 1.30, 1.35, 1.40, 1.45, 1.50 |
|
90 |
+
+---------------------------+-----------------------------------------------------+
|
91 |
+
| Heterogeneous Categories | V1, V3, V5 |
|
92 |
+
+---------------------------+-----------------------------------------------------+
|
93 |
+
| Air Kerma | any numerical value |
|
94 |
+
+---------------------------+-----------------------------------------------------+
|
95 |
+
| Air Kerma Units | R, mGy, mrad |
|
96 |
+
+---------------------------+-----------------------------------------------------+
|
97 |
+
| MGD Units | mGy, mrad |
|
98 |
+
+---------------------------+-----------------------------------------------------+
|
99 |
+
|
100 |
+
|
101 |
+
Table 1. Summary of parameters and their inputs.
|
102 |
+
|
103 |
+
|
104 |
+
+----------------------+------------------------------------------------------------------+
|
105 |
+
| Button | Function |
|
106 |
+
+======================+==================================================================+
|
107 |
+
| Input Incident | Opens file prompt where you select your input incident file. |
|
108 |
+
| Spectrum | The GUI will then read the input file and pull the keV and |
|
109 |
+
| | counts from the file. It further prints the shortened file onto |
|
110 |
+
| | the text box. |
|
111 |
+
+----------------------+------------------------------------------------------------------+
|
112 |
+
| Graph Spectrum | Graphs the inputted spectrum. |
|
113 |
+
+----------------------+------------------------------------------------------------------+
|
114 |
+
| Clear Text | Clears the text box. |
|
115 |
+
+----------------------+------------------------------------------------------------------+
|
116 |
+
| Calculate Dose | After filling all the necessary parameters, pressing this |
|
117 |
+
| | button will calculate and display the estimated mean glandular |
|
118 |
+
| | dose along with the selected values of the parameters. |
|
119 |
+
+----------------------+------------------------------------------------------------------+
|
120 |
+
|
121 |
+
Table 2. Summary of Buttons and their functions.
|
122 |
+
|
123 |
+
The chosen incident spectrum file must have a specific format which differs for the method chosen. This format is further elucidated in the Incident Spectrum Format section found below.
|
124 |
+
|
125 |
+
Incident Spectrum Format
|
126 |
+
========================
|
127 |
+
|
128 |
+
First, the incident spectrum must be saved in a text file (typically a ‘.txt’ file but any text file format is accepted) and it can have any name (there is no naming convention). Next, the text file inputs must be in the form of two columns where the keV is the first column and the counts is the second column. It should be noted that keV uses a step size of 0.5. Any step size can be used. The Hernandez Heterogeneous BCT DgN coefficients are interpolated to fit any step size.
|
129 |
+
|
130 |
+
Furthermore, Sarno Incident Spectrum and Hernandez Heterogeneous BCT take different ranges of values. Sarno Incident Spectrum uses a keV range of 8-80 keV inclusive. Hernandez Heterogeneous BCT, on the other hand, uses a range of 7-90 keV inclusive.
|
PyBDC/Doc/requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
sphinx
|
2 |
+
sphinx_rtd_theme
|
PyBDC/Dosage_Test_Case_spectrum_55kVp2mmAl.xlsx
ADDED
Binary file (9.33 kB). View file
|
|
PyBDC/License
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
BSD 3-Clause License
|
2 |
+
|
3 |
+
Copyright (c) 2024, Harsha Marupudi, Joseph Manus, Bahaa Ghammraoui
|
4 |
+
All rights reserved.
|
5 |
+
|
6 |
+
Redistribution and use in source and binary forms, with or without
|
7 |
+
modification, are permitted provided that the following conditions are met:
|
8 |
+
|
9 |
+
1. Redistributions of source code must retain the above copyright notice, this
|
10 |
+
list of conditions and the following disclaimer.
|
11 |
+
|
12 |
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
13 |
+
this list of conditions and the following disclaimer in the documentation
|
14 |
+
and/or other materials provided with the distribution.
|
15 |
+
|
16 |
+
3. Neither the name of the copyright holder nor the names of its
|
17 |
+
contributors may be used to endorse or promote products derived from
|
18 |
+
this software without specific prior written permission.
|
19 |
+
|
20 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
23 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
24 |
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25 |
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26 |
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27 |
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
28 |
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29 |
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
PyBDC/Paper citations.txt
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Paper citations:
|
2 |
+
|
3 |
+
Sechopoulos, I., Feng, S. S., & D'Orsi, C. J. (2010). Dosimetric characterization of a dedicated breast computed
|
4 |
+
tomography clinical prototype. Medical physics, 37(8), 4110–4120. https://doi.org/10.1118/1.3457331
|
5 |
+
|
6 |
+
Sarno, A., Mettivier, G., Tucciariello, R. M., Bliznakova, K., Boone, J. M., Sechopoulos, I., Di Lillo, F., & Russo, P. (2018).
|
7 |
+
Monte Carlo evaluation of glandular dose in cone-beam X-ray computed tomography dedicated to the breast: Homogeneous and
|
8 |
+
heterogeneous breast models. Physica medica : PM : an international journal devoted to the applications of physics to medicine
|
9 |
+
and biology : official journal of the Italian Association of Biomedical Physics (AIFB), 51, 99–107.
|
10 |
+
https://doi.org/10.1016/j.ejmp.2018.05.021
|
11 |
+
|
12 |
+
Hernandez, A. M., & Boone, J. M. (2017). Average glandular dose coefficients for pendant-geometry breast CT using
|
13 |
+
realistic breast phantoms. Medical physics, 44(10), 5096–5105. https://doi.org/10.1002/mp.12477
|
PyBDC/PyBDC.py
ADDED
@@ -0,0 +1,859 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
Created on Tue Feb 28 13:21:41 2023
|
5 |
+
|
6 |
+
@author: DIDSR
|
7 |
+
"""
|
8 |
+
|
9 |
+
# %% import necessary modules
|
10 |
+
import argparse
|
11 |
+
from tkinter import filedialog, Menu, IntVar, W
|
12 |
+
import customtkinter
|
13 |
+
import numpy as np
|
14 |
+
from matplotlib.pyplot import (
|
15 |
+
style as plt_style,
|
16 |
+
ioff as plt_ioff,
|
17 |
+
figure as plt_figure,
|
18 |
+
rcParams as params,
|
19 |
+
)
|
20 |
+
|
21 |
+
plt_ioff() # suppress pyplot popups
|
22 |
+
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
23 |
+
import tomli
|
24 |
+
from dose_equations import (
|
25 |
+
Sarno_mono_dgn,
|
26 |
+
Sarno_poly_dgn,
|
27 |
+
sarno_dgnct,
|
28 |
+
Hernandez_hetero_mono_dgn,
|
29 |
+
exposure_per_fluence,
|
30 |
+
Sechopoulos_poly_dgn,
|
31 |
+
)
|
32 |
+
|
33 |
+
# %% to set more appropriate font size for the UI (example, running from container may require UI to have larger font size)
|
34 |
+
dict_font_size_set = {1: 14, 2: 24}
|
35 |
+
|
36 |
+
font_size = None
|
37 |
+
|
38 |
+
|
39 |
+
# %% important functions
|
40 |
+
# quit me function
|
41 |
+
def quit_me():
|
42 |
+
root.quit()
|
43 |
+
root.destroy()
|
44 |
+
|
45 |
+
|
46 |
+
# calculate polyenergetic normalized glandular dose coefficients (pDgN) from specified breast models
|
47 |
+
def calculate_pDgNct(*values):
|
48 |
+
keV = values[2]
|
49 |
+
I = values[3]
|
50 |
+
psiE = np.array(list(map(exposure_per_fluence, keV)))
|
51 |
+
|
52 |
+
if values[0] == "Sarno Koning":
|
53 |
+
variables = values[1]
|
54 |
+
DgNctE = np.array(
|
55 |
+
list(
|
56 |
+
map(
|
57 |
+
sarno_dgnct,
|
58 |
+
variables[:, 0],
|
59 |
+
variables[:, 1],
|
60 |
+
variables[:, 2],
|
61 |
+
variables[:, 3],
|
62 |
+
variables[:, 4],
|
63 |
+
variables[:, 5],
|
64 |
+
variables[:, 6],
|
65 |
+
variables[:, 7],
|
66 |
+
keV,
|
67 |
+
)
|
68 |
+
)
|
69 |
+
)
|
70 |
+
pDgN = np.sum(I * psiE * DgNctE) / np.sum(I * psiE)
|
71 |
+
elif values[0] == "Hernandez":
|
72 |
+
DgN_list = np.array(values[1])
|
73 |
+
pDgN = np.sum(I * psiE * DgN_list) / (np.sum(I * psiE))
|
74 |
+
|
75 |
+
return pDgN
|
76 |
+
|
77 |
+
|
78 |
+
# read method outputs display in GUI specifications for certian methods
|
79 |
+
with open("method_specific_inputs.toml", "rb") as file_method_specific_inputs:
|
80 |
+
config_method_specific_inputs = tomli.load(file_method_specific_inputs)
|
81 |
+
|
82 |
+
|
83 |
+
# %%% Main code
|
84 |
+
|
85 |
+
|
86 |
+
class Main_Window:
|
87 |
+
# %% build the gui frames
|
88 |
+
def __init__(self, master):
|
89 |
+
self.master = master
|
90 |
+
# create the menubar
|
91 |
+
menubar = Menu(master)
|
92 |
+
root.config(menu=menubar)
|
93 |
+
helpmenu = Menu(menubar, tearoff=0)
|
94 |
+
helpmenu.add_command(label="Quick Start Guide", command=self.help_command)
|
95 |
+
menubar.add_cascade(label="Help", menu=helpmenu)
|
96 |
+
menubar.add_command(label="Exit", command=lambda: quit_me())
|
97 |
+
|
98 |
+
# create the different frames
|
99 |
+
self.methods_frame = customtkinter.CTkFrame(master=master)
|
100 |
+
self.methods_frame.grid(row=0, column=0, ipady=36)
|
101 |
+
self.inputs_frame = customtkinter.CTkFrame(master=master)
|
102 |
+
self.inputs_frame.grid(row=0, column=1, padx=10, pady=5, ipadx=6)
|
103 |
+
self.kerma_spec_frame = customtkinter.CTkFrame(master=master)
|
104 |
+
self.kerma_spec_frame.grid(row=0, column=2, pady=5, ipady=24, ipadx=4)
|
105 |
+
self.output_frame = customtkinter.CTkFrame(master=master)
|
106 |
+
self.output_frame.grid(row=1, column=0, ipady=12)
|
107 |
+
self.graph_frame = customtkinter.CTkFrame(master=master)
|
108 |
+
self.graph_frame.grid(row=1, column=1, columnspan=2, padx=4, ipady=14)
|
109 |
+
# create figure
|
110 |
+
self.keV = []
|
111 |
+
self.I = []
|
112 |
+
self.plot_spectra()
|
113 |
+
|
114 |
+
# %% add the different methods
|
115 |
+
self.method_label = customtkinter.CTkLabel(
|
116 |
+
master=self.methods_frame,
|
117 |
+
text="Choose any of the following BCT methods:",
|
118 |
+
font=("Roman", font_size),
|
119 |
+
)
|
120 |
+
self.method_chosen = IntVar(root)
|
121 |
+
self.method_chosen.set(2)
|
122 |
+
self.current_method = 1
|
123 |
+
self.Sarno_radiobutton = customtkinter.CTkRadioButton(
|
124 |
+
master=self.methods_frame,
|
125 |
+
text="Sarno 49 kVp W Spectra",
|
126 |
+
command=lambda: self.change_inputs(),
|
127 |
+
variable=self.method_chosen,
|
128 |
+
value=1,
|
129 |
+
radiobutton_width=14,
|
130 |
+
radiobutton_height=14,
|
131 |
+
font=("Roman", font_size),
|
132 |
+
)
|
133 |
+
|
134 |
+
self.Sarno_incident_radiobutton = customtkinter.CTkRadioButton(
|
135 |
+
master=self.methods_frame,
|
136 |
+
text="Sarno Any Spectrum",
|
137 |
+
command=lambda: self.change_inputs(),
|
138 |
+
variable=self.method_chosen,
|
139 |
+
value=2,
|
140 |
+
radiobutton_width=14,
|
141 |
+
radiobutton_height=14,
|
142 |
+
font=("Roman", font_size),
|
143 |
+
)
|
144 |
+
|
145 |
+
self.Hernandez_radiobutton = customtkinter.CTkRadioButton(
|
146 |
+
master=self.methods_frame,
|
147 |
+
text="Hernandez Any Spectrum",
|
148 |
+
command=lambda: self.change_inputs(),
|
149 |
+
variable=self.method_chosen,
|
150 |
+
value=3,
|
151 |
+
radiobutton_width=14,
|
152 |
+
radiobutton_height=14,
|
153 |
+
font=("Roman", font_size),
|
154 |
+
)
|
155 |
+
|
156 |
+
self.Sechopoulos_radiobutton = customtkinter.CTkRadioButton(
|
157 |
+
master=self.methods_frame,
|
158 |
+
text="Sechopoulos 49 kVp W Spectra",
|
159 |
+
command=lambda: self.change_inputs(),
|
160 |
+
variable=self.method_chosen,
|
161 |
+
value=4,
|
162 |
+
radiobutton_width=14,
|
163 |
+
radiobutton_height=14,
|
164 |
+
font=("Roman", font_size),
|
165 |
+
)
|
166 |
+
|
167 |
+
self.method_label.pack(padx=20, pady=5, anchor=W)
|
168 |
+
self.Sarno_incident_radiobutton.pack(padx=20, pady=5, anchor=W)
|
169 |
+
self.Hernandez_radiobutton.pack(padx=20, pady=5, anchor=W)
|
170 |
+
self.Sarno_radiobutton.pack(padx=20, pady=5, anchor=W)
|
171 |
+
self.Sechopoulos_radiobutton.pack(padx=20, pady=5, anchor=W)
|
172 |
+
|
173 |
+
# %% fill in the main input box
|
174 |
+
self.Breast_diameter_label = customtkinter.CTkLabel(
|
175 |
+
master=self.inputs_frame,
|
176 |
+
text="Breast Diameter (cm):",
|
177 |
+
font=("Roman", font_size),
|
178 |
+
)
|
179 |
+
self.Breast_diameter_combo = customtkinter.CTkComboBox(
|
180 |
+
master=self.inputs_frame,
|
181 |
+
values=["8", "10", "12", "14", "19", "18"],
|
182 |
+
width=120,
|
183 |
+
state="readonly",
|
184 |
+
font=("Roman", font_size),
|
185 |
+
)
|
186 |
+
self.Breast_diameter_combo.set("8")
|
187 |
+
|
188 |
+
self.Breast_height_label = customtkinter.CTkLabel(
|
189 |
+
master=self.inputs_frame, text="Breast Height:", font=("Roman", font_size)
|
190 |
+
)
|
191 |
+
self.Breast_height_combo = customtkinter.CTkComboBox(
|
192 |
+
master=self.inputs_frame,
|
193 |
+
values=["1 x radius", "1.5 x radius", "2 x radius"],
|
194 |
+
width=120,
|
195 |
+
state="readonly",
|
196 |
+
font=("Roman", font_size),
|
197 |
+
)
|
198 |
+
self.Breast_height_combo.set("1 x radius")
|
199 |
+
self.Breast_glandularity_label = customtkinter.CTkLabel(
|
200 |
+
master=self.inputs_frame,
|
201 |
+
text="Breast Glandularity:",
|
202 |
+
font=("Roman", font_size),
|
203 |
+
)
|
204 |
+
self.Breast_glandularity_combo = customtkinter.CTkComboBox(
|
205 |
+
master=self.inputs_frame,
|
206 |
+
values=["0.1%", "14.3%", "25%", "50%", "100%"],
|
207 |
+
width=120,
|
208 |
+
state="readonly",
|
209 |
+
font=("Roman", font_size),
|
210 |
+
)
|
211 |
+
self.Breast_glandularity_combo.set("0.1%")
|
212 |
+
|
213 |
+
self.HVL_label = customtkinter.CTkLabel(
|
214 |
+
master=self.inputs_frame, text="HVL (mm Al):", font=("Roman", font_size)
|
215 |
+
)
|
216 |
+
self.HVL_combo = customtkinter.CTkComboBox(
|
217 |
+
master=self.inputs_frame,
|
218 |
+
values=["1.25", "1.30", "1.35", "1.40", "1.45", "1.50"],
|
219 |
+
width=120,
|
220 |
+
state="readonly",
|
221 |
+
font=("Roman", font_size),
|
222 |
+
)
|
223 |
+
self.HVL_combo.set("1.25")
|
224 |
+
|
225 |
+
self.VGF_label = customtkinter.CTkLabel(
|
226 |
+
master=self.inputs_frame,
|
227 |
+
text="Heterogeneous Categories:",
|
228 |
+
font=("Roman", font_size),
|
229 |
+
)
|
230 |
+
self.VGF_combo = customtkinter.CTkComboBox(
|
231 |
+
master=self.inputs_frame,
|
232 |
+
values=["V1 = 19.9%", "V3 = 9.5%", "V5 = 3.8%"],
|
233 |
+
width=120,
|
234 |
+
state="readonly",
|
235 |
+
font=("Roman", font_size),
|
236 |
+
) # V1 = 19.9%, V3 = 9.5%, V5 = 3.8%
|
237 |
+
self.VGF_combo.set("V1 = 19.9%")
|
238 |
+
self.input_spectra_button = customtkinter.CTkButton(
|
239 |
+
master=self.inputs_frame,
|
240 |
+
fg_color=("black", "lightgray"),
|
241 |
+
width=100,
|
242 |
+
border_width=0,
|
243 |
+
corner_radius=2,
|
244 |
+
text="Upload Incident Spectrum File",
|
245 |
+
font=("Roman", font_size),
|
246 |
+
command=lambda: self.browse_files(),
|
247 |
+
)
|
248 |
+
self.Breast_diameter_label.grid(row=0, column=0, pady=5, padx=4, sticky=W)
|
249 |
+
self.Breast_diameter_combo.grid(row=0, column=1, pady=5, padx=10, sticky=W)
|
250 |
+
self.Breast_height_label.grid(row=1, column=0, pady=5, padx=4, sticky=W)
|
251 |
+
self.Breast_height_combo.grid(row=1, column=1, pady=5)
|
252 |
+
self.Breast_glandularity_label.grid(row=2, column=0, pady=5, padx=4, sticky=W)
|
253 |
+
self.Breast_glandularity_combo.grid(row=2, column=1, pady=5)
|
254 |
+
self.HVL_label.grid(row=3, column=0, pady=5, padx=4, sticky=W)
|
255 |
+
self.HVL_combo.grid(row=3, column=1, pady=5)
|
256 |
+
self.HVL_combo.configure(state="disabled")
|
257 |
+
self.VGF_label.grid(row=4, column=0, pady=5, padx=4, sticky=W)
|
258 |
+
self.VGF_combo.grid(row=4, column=1, pady=5, padx=12, sticky=W)
|
259 |
+
self.VGF_combo.configure(state="disabled")
|
260 |
+
self.input_spectra_button.grid(row=5, column=0, pady=5, columnspan=2)
|
261 |
+
|
262 |
+
# %% create text box and buttons for output frame
|
263 |
+
self.output_textbox = customtkinter.CTkTextbox(
|
264 |
+
self.output_frame, width=285, height=305, font=("Roman", font_size)
|
265 |
+
)
|
266 |
+
self.output_textbox.tag_config("green", foreground="green")
|
267 |
+
self.output_textbox.configure(state="normal")
|
268 |
+
self.output_textbox.insert(
|
269 |
+
"end",
|
270 |
+
f'{"".join(config_method_specific_inputs["method_specific_inputs"]["Sarno_specific_outputs"])}',
|
271 |
+
"green",
|
272 |
+
)
|
273 |
+
self.output_textbox.configure(state="disabled")
|
274 |
+
self.clear_button = customtkinter.CTkButton(
|
275 |
+
master=self.output_frame,
|
276 |
+
width=120,
|
277 |
+
border_width=0,
|
278 |
+
corner_radius=8,
|
279 |
+
text="Clear Text",
|
280 |
+
font=("Roman", font_size),
|
281 |
+
command=lambda: self.clear_text(),
|
282 |
+
)
|
283 |
+
self.calculate_button = customtkinter.CTkButton(
|
284 |
+
master=self.output_frame,
|
285 |
+
width=120,
|
286 |
+
border_width=0,
|
287 |
+
corner_radius=8,
|
288 |
+
text="Calculate Dose",
|
289 |
+
font=("Roman", font_size),
|
290 |
+
command=lambda: self.calculate_dose(),
|
291 |
+
)
|
292 |
+
|
293 |
+
self.clear_button.grid(row=1, column=0, pady=5, padx=4)
|
294 |
+
self.output_textbox.grid(row=0, column=0, columnspan=3)
|
295 |
+
self.output_textbox.configure(state="disabled") # insert at line 0 character 0
|
296 |
+
self.calculate_button.grid(row=1, column=1, pady=5, padx=4)
|
297 |
+
|
298 |
+
# %% create air kerma inputs
|
299 |
+
|
300 |
+
self.mAs_label = customtkinter.CTkLabel(
|
301 |
+
master=self.kerma_spec_frame,
|
302 |
+
text="mAs per Projection:",
|
303 |
+
font=("Roman", font_size),
|
304 |
+
)
|
305 |
+
self.mAs_entry = customtkinter.CTkEntry(master=self.kerma_spec_frame, width=80)
|
306 |
+
self.mAs_units_combo = customtkinter.CTkComboBox(
|
307 |
+
master=self.kerma_spec_frame,
|
308 |
+
values=["mAs"],
|
309 |
+
width=80,
|
310 |
+
state="readonly",
|
311 |
+
font=("Roman", font_size),
|
312 |
+
)
|
313 |
+
|
314 |
+
self.air_kerma_label = customtkinter.CTkLabel(
|
315 |
+
master=self.kerma_spec_frame,
|
316 |
+
text="Air kerma per Projection:",
|
317 |
+
font=("Roman", font_size),
|
318 |
+
)
|
319 |
+
self.air_kerma_entry = customtkinter.CTkEntry(
|
320 |
+
master=self.kerma_spec_frame, width=80
|
321 |
+
)
|
322 |
+
self.input_label = customtkinter.CTkLabel(
|
323 |
+
master=self.kerma_spec_frame,
|
324 |
+
text="Air kerma Units:",
|
325 |
+
font=("Roman", font_size),
|
326 |
+
)
|
327 |
+
self.air_kerma_units_combo = customtkinter.CTkComboBox(
|
328 |
+
master=self.kerma_spec_frame,
|
329 |
+
values=["mrad", "mGy", "R", "mR"],
|
330 |
+
width=80,
|
331 |
+
state="readonly",
|
332 |
+
font=("Roman", font_size),
|
333 |
+
)
|
334 |
+
self.air_kerma_units_combo.set("R")
|
335 |
+
self.air_kerma_output_label = customtkinter.CTkLabel(
|
336 |
+
master=self.kerma_spec_frame,
|
337 |
+
text="MGD Units:",
|
338 |
+
anchor=W,
|
339 |
+
font=("Roman", font_size),
|
340 |
+
)
|
341 |
+
self.output_units = customtkinter.CTkComboBox(
|
342 |
+
master=self.kerma_spec_frame,
|
343 |
+
values=["mrad", "mGy"],
|
344 |
+
width=80,
|
345 |
+
state="readonly",
|
346 |
+
font=("Roman", font_size),
|
347 |
+
)
|
348 |
+
self.output_units.set("mrad")
|
349 |
+
|
350 |
+
self.number_projections_label = customtkinter.CTkLabel(
|
351 |
+
master=self.kerma_spec_frame,
|
352 |
+
text="Number of Projections: ",
|
353 |
+
font=("Roman", font_size),
|
354 |
+
)
|
355 |
+
self.number_projections_entry = customtkinter.CTkEntry(
|
356 |
+
master=self.kerma_spec_frame, width=80
|
357 |
+
)
|
358 |
+
|
359 |
+
self.graph_spectra = customtkinter.CTkButton(
|
360 |
+
master=self.kerma_spec_frame,
|
361 |
+
width=220,
|
362 |
+
border_width=1,
|
363 |
+
corner_radius=10,
|
364 |
+
text="Graph Spectrum",
|
365 |
+
font=("Roman", font_size),
|
366 |
+
command=self.plot_spectra,
|
367 |
+
)
|
368 |
+
|
369 |
+
self.air_kerma_label.grid(row=1, column=0, pady=5, padx=4, sticky=W)
|
370 |
+
self.air_kerma_entry.grid(row=1, column=1, pady=5, padx=12, sticky=W)
|
371 |
+
self.number_projections_label.grid(row=2, column=0, pady=5, padx=4, sticky=W)
|
372 |
+
self.number_projections_entry.grid(row=2, column=1, pady=5, padx=12, sticky=W)
|
373 |
+
self.mAs_label.grid(row=5, column=0, pady=5, padx=4, sticky=W)
|
374 |
+
self.mAs_entry.grid(row=5, column=1, pady=5, padx=12, sticky=W)
|
375 |
+
self.input_label.grid(row=3, column=0, pady=5, padx=4, sticky=W)
|
376 |
+
self.air_kerma_units_combo.grid(row=3, column=1, pady=5, padx=12, sticky=W)
|
377 |
+
self.air_kerma_output_label.grid(row=4, column=0, pady=5, padx=4, sticky=W)
|
378 |
+
self.output_units.grid(row=4, column=1, pady=5, padx=12, sticky=W)
|
379 |
+
self.graph_spectra.grid(row=6, column=0, pady=5, columnspan=2)
|
380 |
+
self.graph_spectra.configure(state="disabled")
|
381 |
+
|
382 |
+
# %% important functions
|
383 |
+
# add help command
|
384 |
+
def help_command(self):
|
385 |
+
pop_up = customtkinter.CTkToplevel()
|
386 |
+
textbox = customtkinter.CTkTextbox(master=pop_up, width=800, height=500)
|
387 |
+
textbox.pack(fill="both")
|
388 |
+
|
389 |
+
with open("CT_Dose_Calculate_Quick_Guide.txt", "r") as file:
|
390 |
+
data = file.read()
|
391 |
+
|
392 |
+
textbox.insert("end", f"{data}")
|
393 |
+
textbox.configure(state="disabled")
|
394 |
+
|
395 |
+
# change the method specific inputs based on selection
|
396 |
+
def change_inputs(self):
|
397 |
+
current_method = self.method_chosen.get()
|
398 |
+
|
399 |
+
if current_method == 1: # Sarno 49 kVp W Spectra
|
400 |
+
# enable and disable buttons
|
401 |
+
self.VGF_combo.configure(state="disabled")
|
402 |
+
self.input_spectra_button.configure(state="disabled")
|
403 |
+
self.Breast_diameter_combo.configure(state="normal")
|
404 |
+
self.Breast_height_combo.configure(state="normal")
|
405 |
+
self.Breast_glandularity_combo.configure(state="normal")
|
406 |
+
self.HVL_combo.configure(state="normal")
|
407 |
+
self.graph_spectra.configure(state="disabled")
|
408 |
+
self.Breast_glandularity_combo.configure(
|
409 |
+
values=["0.1%", "14.3%", "25%", "50%", "75%", "100%"]
|
410 |
+
)
|
411 |
+
self.Breast_glandularity_combo.set("0.1%")
|
412 |
+
self.Breast_diameter_combo.configure(
|
413 |
+
values=["8", "10", "12", "14", "19", "18"]
|
414 |
+
)
|
415 |
+
self.Breast_diameter_combo.set("8")
|
416 |
+
self.Breast_height_combo.configure(
|
417 |
+
values=["1 x radius", "1.5 x radius", "2 x radius"]
|
418 |
+
)
|
419 |
+
self.Breast_height_combo.set("1 x radius")
|
420 |
+
self.output_textbox.configure(state="normal")
|
421 |
+
self.output_textbox.delete("0.0", "end")
|
422 |
+
self.output_textbox.configure(state="normal")
|
423 |
+
self.output_textbox.insert(
|
424 |
+
"end",
|
425 |
+
f'{"".join(config_method_specific_inputs["method_specific_inputs"]["Sarno_49_specific_output"])}',
|
426 |
+
"green",
|
427 |
+
)
|
428 |
+
self.output_textbox.configure(state="disabled")
|
429 |
+
self.keV = []
|
430 |
+
self.I = []
|
431 |
+
self.plot_spectra()
|
432 |
+
|
433 |
+
elif current_method == 2: # Sarno any spectrum
|
434 |
+
self.VGF_combo.configure(state="disabled")
|
435 |
+
self.input_spectra_button.configure(state="normal")
|
436 |
+
self.Breast_diameter_combo.configure(state="normal")
|
437 |
+
self.Breast_height_combo.configure(state="normal")
|
438 |
+
self.Breast_glandularity_combo.configure(state="normal")
|
439 |
+
self.HVL_combo.configure(state="disabled")
|
440 |
+
self.graph_spectra.configure(state="disabled")
|
441 |
+
self.Breast_glandularity_combo.configure(
|
442 |
+
values=["0.1%", "14.3%", "25%", "50%", "75%", "100%"]
|
443 |
+
)
|
444 |
+
self.Breast_glandularity_combo.set("0.1%")
|
445 |
+
self.Breast_diameter_combo.configure(
|
446 |
+
values=["8", "10", "12", "14", "19", "18"]
|
447 |
+
)
|
448 |
+
self.Breast_diameter_combo.set("8")
|
449 |
+
self.Breast_height_combo.configure(
|
450 |
+
values=["1 x radius", "1.5 x radius", "2 x radius"]
|
451 |
+
)
|
452 |
+
self.Breast_height_combo.set("1 x radius")
|
453 |
+
self.output_textbox.configure(state="normal")
|
454 |
+
self.output_textbox.delete("0.0", "end")
|
455 |
+
self.output_textbox.insert(
|
456 |
+
"end",
|
457 |
+
f'{"".join(config_method_specific_inputs["method_specific_inputs"]["Sarno_specific_outputs"])}',
|
458 |
+
"green",
|
459 |
+
)
|
460 |
+
self.output_textbox.configure(state="disabled")
|
461 |
+
self.keV = []
|
462 |
+
self.I = []
|
463 |
+
self.plot_spectra()
|
464 |
+
|
465 |
+
elif current_method == 3: # Hernandez any spectrum
|
466 |
+
self.VGF_combo.configure(state="normal")
|
467 |
+
self.input_spectra_button.configure(state="normal")
|
468 |
+
self.Breast_diameter_combo.configure(state="disabled")
|
469 |
+
self.Breast_height_combo.configure(state="disabled")
|
470 |
+
self.Breast_glandularity_combo.configure(state="disabled")
|
471 |
+
self.HVL_combo.configure(state="disabled")
|
472 |
+
self.graph_spectra.configure(state="disabled")
|
473 |
+
self.output_textbox.configure(state="normal")
|
474 |
+
self.output_textbox.delete("0.0", "end")
|
475 |
+
self.output_textbox.insert(
|
476 |
+
"end",
|
477 |
+
f'{"".join(config_method_specific_inputs["method_specific_inputs"]["Hernandez_specific_output"])}',
|
478 |
+
"green",
|
479 |
+
)
|
480 |
+
self.output_textbox.configure(state="disabled")
|
481 |
+
self.keV = []
|
482 |
+
self.I = []
|
483 |
+
self.plot_spectra()
|
484 |
+
|
485 |
+
else: # Sechopoulus method
|
486 |
+
self.VGF_combo.configure(state="disabled")
|
487 |
+
self.input_spectra_button.configure(state="disabled")
|
488 |
+
self.Breast_diameter_combo.configure(state="normal")
|
489 |
+
self.Breast_height_combo.configure(state="normal")
|
490 |
+
self.Breast_glandularity_combo.configure(state="normal")
|
491 |
+
self.HVL_combo.configure(state="disabled")
|
492 |
+
self.graph_spectra.configure(state="disabled")
|
493 |
+
self.output_textbox.configure(state="normal")
|
494 |
+
self.output_textbox.delete("0.0", "end")
|
495 |
+
self.output_textbox.insert(
|
496 |
+
"end",
|
497 |
+
f'{"".join(config_method_specific_inputs["method_specific_inputs"]["Sechopoulos_specific_output"])}',
|
498 |
+
"green",
|
499 |
+
)
|
500 |
+
self.output_textbox.configure(state="disabled")
|
501 |
+
self.Breast_glandularity_combo.configure(
|
502 |
+
values=["1%", "14.3%", "25%", "50%", "75%", "100%"]
|
503 |
+
)
|
504 |
+
self.Breast_glandularity_combo.set("1%")
|
505 |
+
self.Breast_diameter_combo.configure(values=["10", "12", "14", "19", "18"])
|
506 |
+
self.Breast_diameter_combo.set("10")
|
507 |
+
self.Breast_height_combo.configure(
|
508 |
+
values=["0.5 x diameter", "0.75 x diameter", "1 x diameter"]
|
509 |
+
)
|
510 |
+
self.Breast_height_combo.set("0.5 x diameter")
|
511 |
+
self.keV = []
|
512 |
+
self.I = []
|
513 |
+
self.plot_spectra()
|
514 |
+
|
515 |
+
# browse for incident spectrum
|
516 |
+
def browse_files(self):
|
517 |
+
# read and output textfile
|
518 |
+
self.input_txt_file = filedialog.askopenfilename(
|
519 |
+
initialdir="/", title="Select a File", filetypes=[("all files", "*.*")]
|
520 |
+
)
|
521 |
+
self.display_txt_file = self.input_txt_file.split("/")[-1]
|
522 |
+
self.output_textbox.configure(state="normal")
|
523 |
+
self.output_textbox.insert(
|
524 |
+
"end", f"\nInputted incident spectrum: \n{self.display_txt_file}", "\n"
|
525 |
+
)
|
526 |
+
self.output_textbox.configure(state="disabled")
|
527 |
+
|
528 |
+
try:
|
529 |
+
# get keV and I
|
530 |
+
self.keV, self.I = self.read_input_spectra()
|
531 |
+
self.minimum = min(self.keV)
|
532 |
+
self.maximum = max(self.keV)
|
533 |
+
method = self.method_chosen.get()
|
534 |
+
|
535 |
+
if method == 3:
|
536 |
+
if self.minimum < 9 or self.maximum > 70:
|
537 |
+
raise (ValueError)
|
538 |
+
elif method == 2:
|
539 |
+
if self.minimum < 8 or self.maximum > 80:
|
540 |
+
raise (ValueError)
|
541 |
+
|
542 |
+
self.graph_spectra.configure(state="normal")
|
543 |
+
|
544 |
+
# account for possible errors
|
545 |
+
except UnicodeDecodeError:
|
546 |
+
pop_up = customtkinter.CTkToplevel()
|
547 |
+
customtkinter.CTkLabel(
|
548 |
+
pop_up, text="Please enter a valid text file", font=("Roman", font_size)
|
549 |
+
).pack()
|
550 |
+
|
551 |
+
except ValueError:
|
552 |
+
pop_up = customtkinter.CTkToplevel()
|
553 |
+
customtkinter.CTkLabel(
|
554 |
+
pop_up,
|
555 |
+
text="For Hernadez Any spectrum, please enter spectrum ranging from 9 to 70 keV",
|
556 |
+
font=("Roman", font_size),
|
557 |
+
).pack()
|
558 |
+
customtkinter.CTkLabel(
|
559 |
+
pop_up,
|
560 |
+
text="For Sarno Any Spectrum, please enter spectrum ranging from 8 to 80 keV",
|
561 |
+
font=("Roman", font_size),
|
562 |
+
).pack()
|
563 |
+
|
564 |
+
# read input spectra
|
565 |
+
def read_input_spectra(self):
|
566 |
+
with open(self.input_txt_file, "r") as file:
|
567 |
+
keV = []
|
568 |
+
I = []
|
569 |
+
data = file.readlines()
|
570 |
+
for line in data:
|
571 |
+
line = line.split()
|
572 |
+
keV.append(float(line[0]))
|
573 |
+
I.append(float(line[1]))
|
574 |
+
|
575 |
+
return keV, I
|
576 |
+
|
577 |
+
# clear text
|
578 |
+
def clear_text(self):
|
579 |
+
self.output_textbox.configure(state="normal")
|
580 |
+
self.output_textbox.delete("0.0", "end")
|
581 |
+
self.output_textbox.configure(state="disabled")
|
582 |
+
|
583 |
+
# update plot
|
584 |
+
def plot_spectra(self):
|
585 |
+
try:
|
586 |
+
y_end = max(self.I) * 1.1
|
587 |
+
x_end = max(self.keV) * 1.1
|
588 |
+
file_name = self.display_txt_file
|
589 |
+
except:
|
590 |
+
x_end = 5
|
591 |
+
y_end = 5
|
592 |
+
file_name = "Input Incident Spectrum"
|
593 |
+
|
594 |
+
plt_style.use(["dark_background"])
|
595 |
+
params["figure.figsize"] = [7.50, 3.50]
|
596 |
+
params["figure.autolayout"] = True
|
597 |
+
self.figure = plt_figure(figsize=(7.6, 4.2), dpi=100)
|
598 |
+
axes = self.figure.add_subplot(111)
|
599 |
+
axes.plot(self.keV, self.I, "b-")
|
600 |
+
axes.set_title(f"{file_name}")
|
601 |
+
axes.set_xlabel("Energy (keV)", fontsize=11)
|
602 |
+
axes.set_ylabel("Intensity (counts)", fontsize=11)
|
603 |
+
axes.set_xlim(0, x_end)
|
604 |
+
axes.set_ylim([0, y_end])
|
605 |
+
chart = FigureCanvasTkAgg(self.figure, master=self.graph_frame)
|
606 |
+
chart.get_tk_widget().grid(row=0, column=0, columnspan=2)
|
607 |
+
|
608 |
+
# calculate mean glandur dosage from user specificed inputs
|
609 |
+
def calculate_mgd(
|
610 |
+
self, air_kerma_input, air_kerma, dgn, output_units, number_of_projections
|
611 |
+
):
|
612 |
+
# unit conversions based on user selection
|
613 |
+
if air_kerma_input != "mGy":
|
614 |
+
if air_kerma_input == "mrad":
|
615 |
+
air_kerma = air_kerma * 0.01 # convert from mrad air kerma to mGy
|
616 |
+
elif air_kerma_input == "R":
|
617 |
+
air_kerma = air_kerma * 8.77 # convert from R to mGy
|
618 |
+
elif air_kerma_input == "mR":
|
619 |
+
air_kerma = air_kerma * 0.00877 # convert from mR to mGy
|
620 |
+
|
621 |
+
mgd = air_kerma * dgn * float(number_of_projections) # in mGy/mGy
|
622 |
+
|
623 |
+
if output_units == "mrad":
|
624 |
+
mgd = mgd * 100 # converts mgd to mrad
|
625 |
+
|
626 |
+
return mgd
|
627 |
+
|
628 |
+
# write inputs to textbox
|
629 |
+
def output_dose(self, *values):
|
630 |
+
self.output_textbox.configure(state="normal")
|
631 |
+
self.output_textbox.insert(
|
632 |
+
"end", f"\n\nMGD = {self.mgd:.4f} {self.output_units.get()}"
|
633 |
+
)
|
634 |
+
self.output_textbox.insert(
|
635 |
+
"end", f" with {self.number_projections_entry.get()} projections"
|
636 |
+
)
|
637 |
+
self.output_textbox.insert("end", f" with {self.mAs_entry.get()} mAs")
|
638 |
+
|
639 |
+
for index in range(len(values)):
|
640 |
+
if index == 0 or index % 2 == 0:
|
641 |
+
self.output_textbox.insert("end", f"\n{values[index]}")
|
642 |
+
else:
|
643 |
+
self.output_textbox.insert("end", f"{values[index]}")
|
644 |
+
|
645 |
+
self.output_textbox.configure(state="disabled")
|
646 |
+
|
647 |
+
# function to calculate dose
|
648 |
+
def calculate_dose(self):
|
649 |
+
# get inputs
|
650 |
+
current_method = self.method_chosen.get()
|
651 |
+
air_kerma_input_units = self.air_kerma_units_combo.get()
|
652 |
+
output_units = self.output_units.get()
|
653 |
+
air_kerma = self.air_kerma_entry.get()
|
654 |
+
number_of_projections = self.number_projections_entry.get()
|
655 |
+
|
656 |
+
try:
|
657 |
+
# numbers only
|
658 |
+
air_kerma_check = len(air_kerma)
|
659 |
+
number_of_projections_check = len(number_of_projections)
|
660 |
+
air_kerma = float(air_kerma) # check if only numbers
|
661 |
+
mAs_per_projection = float(self.mAs_entry.get())
|
662 |
+
air_kerma = mAs_per_projection * air_kerma
|
663 |
+
|
664 |
+
if air_kerma_check == 0 or number_of_projections_check == 0:
|
665 |
+
raise (ValueError)
|
666 |
+
|
667 |
+
elif current_method == 2 or current_method == 3:
|
668 |
+
kev_check = len(self.keV)
|
669 |
+
if kev_check == 0:
|
670 |
+
raise (TypeError)
|
671 |
+
|
672 |
+
# calculate mgd based on specified model
|
673 |
+
if current_method == 1: # Sarno 49 kVp W spectra
|
674 |
+
# get parameters
|
675 |
+
HVL = self.HVL_combo.get()
|
676 |
+
breast_diameter = self.Breast_diameter_combo.get()
|
677 |
+
breast_glandularity = self.Breast_glandularity_combo.get()
|
678 |
+
breast_height = "".join(self.Breast_height_combo.get().split(" ")[0:2])
|
679 |
+
|
680 |
+
# calculate polyenergetic dgn coefficients
|
681 |
+
dgn_subtable_breast_height = Sarno_poly_dgn.groupby(
|
682 |
+
["breast height"]
|
683 |
+
).get_group(breast_height)
|
684 |
+
dgn_subtable_glandularity = dgn_subtable_breast_height.groupby(
|
685 |
+
["Glandularity"]
|
686 |
+
).get_group(breast_glandularity)
|
687 |
+
dgn = dgn_subtable_glandularity.loc[float(HVL), str(breast_diameter)]
|
688 |
+
|
689 |
+
# calculate mgd based on pdgn and input parameters
|
690 |
+
self.mgd = self.calculate_mgd(
|
691 |
+
air_kerma_input_units,
|
692 |
+
air_kerma,
|
693 |
+
dgn,
|
694 |
+
output_units,
|
695 |
+
number_of_projections,
|
696 |
+
)
|
697 |
+
|
698 |
+
self.output_dose(
|
699 |
+
"Breast diameter: ",
|
700 |
+
breast_diameter,
|
701 |
+
"HVL: ",
|
702 |
+
HVL,
|
703 |
+
"Breast_glandularity: ",
|
704 |
+
breast_glandularity,
|
705 |
+
"Breast Height: ",
|
706 |
+
self.Breast_height_combo.get(),
|
707 |
+
)
|
708 |
+
|
709 |
+
elif current_method == 2: # Sarno any spectrum
|
710 |
+
breast_diameter = self.Breast_diameter_combo.get()
|
711 |
+
breast_glandularity = self.Breast_glandularity_combo.get()
|
712 |
+
breast_height = "".join(self.Breast_height_combo.get().split(" ")[0:2])
|
713 |
+
|
714 |
+
# get dgn coefficients
|
715 |
+
dgn_subtable_breast_height = Sarno_mono_dgn.groupby(
|
716 |
+
["breast height"]
|
717 |
+
).get_group(breast_height)
|
718 |
+
dgn_subtable_glandularity = dgn_subtable_breast_height.groupby(
|
719 |
+
["Glandularity"]
|
720 |
+
).get_group(breast_glandularity)
|
721 |
+
values = dgn_subtable_glandularity[str(breast_diameter)].tolist()
|
722 |
+
variables = np.zeros((len(self.keV), len(values)))
|
723 |
+
|
724 |
+
for index in range(0, len(values)):
|
725 |
+
variables[:, index] = [float(values[index])] # *len(self.keV)
|
726 |
+
|
727 |
+
# calulate dgn
|
728 |
+
dgn = calculate_pDgNct(
|
729 |
+
"Sarno Koning", variables, self.keV, self.I
|
730 |
+
) # units of mGy/mGy
|
731 |
+
|
732 |
+
self.mgd = self.calculate_mgd(
|
733 |
+
air_kerma_input_units,
|
734 |
+
air_kerma,
|
735 |
+
dgn,
|
736 |
+
output_units,
|
737 |
+
number_of_projections,
|
738 |
+
)
|
739 |
+
|
740 |
+
self.output_dose(
|
741 |
+
"Breast diameter: ",
|
742 |
+
breast_diameter,
|
743 |
+
"Breast Glandularity: ",
|
744 |
+
breast_glandularity,
|
745 |
+
"Breast Height: ",
|
746 |
+
self.Breast_height_combo.get(),
|
747 |
+
)
|
748 |
+
|
749 |
+
elif current_method == 3: # Hernandez any spectrum
|
750 |
+
# get the VGF and DgN list from text file
|
751 |
+
VGF = self.VGF_combo.get().split("=")[0].strip()
|
752 |
+
DgN_list = Hernandez_hetero_mono_dgn.loc[:, VGF].tolist()
|
753 |
+
|
754 |
+
# index the list to fit keV
|
755 |
+
start_index = int(abs(self.minimum - 9))
|
756 |
+
if self.maximum != 70:
|
757 |
+
end_index = int(abs(self.maximum - 9)) + 1
|
758 |
+
else:
|
759 |
+
end_index = -1
|
760 |
+
|
761 |
+
# interpolate the DgN list if necessary
|
762 |
+
Hernandez_keV = list(np.arange(self.minimum, self.maximum + 1))
|
763 |
+
DgN_list = DgN_list[start_index:end_index]
|
764 |
+
interp_DgN_list = np.interp(self.keV, Hernandez_keV, DgN_list)
|
765 |
+
|
766 |
+
# get the DgN coefficients in mGy/mGy
|
767 |
+
dgn = calculate_pDgNct("Hernandez", interp_DgN_list, self.keV, self.I)
|
768 |
+
|
769 |
+
print(dgn)
|
770 |
+
|
771 |
+
# print(dgn)
|
772 |
+
self.mgd = self.calculate_mgd(
|
773 |
+
air_kerma_input_units,
|
774 |
+
air_kerma,
|
775 |
+
dgn,
|
776 |
+
output_units,
|
777 |
+
number_of_projections,
|
778 |
+
)
|
779 |
+
|
780 |
+
self.output_dose("VGF: ", self.VGF_combo.get())
|
781 |
+
|
782 |
+
else: # Sechopoulos method
|
783 |
+
# get parameters
|
784 |
+
breast_diameter = self.Breast_diameter_combo.get()
|
785 |
+
breast_glandularity = self.Breast_glandularity_combo.get()
|
786 |
+
breast_height = float(
|
787 |
+
self.Breast_height_combo.get().split("x")[0]
|
788 |
+
) * float(breast_diameter)
|
789 |
+
|
790 |
+
# calculate dgn for polyenergetic
|
791 |
+
dgn_subtable_breast_height = Sechopoulos_poly_dgn.groupby(
|
792 |
+
["Chest wall-to-nipple distance"]
|
793 |
+
).get_group(breast_height)
|
794 |
+
dgn = dgn_subtable_breast_height[breast_glandularity].tolist()[0]
|
795 |
+
|
796 |
+
# calculate mgd
|
797 |
+
self.mgd = self.calculate_mgd(
|
798 |
+
air_kerma_input_units,
|
799 |
+
air_kerma,
|
800 |
+
dgn,
|
801 |
+
output_units,
|
802 |
+
number_of_projections,
|
803 |
+
)
|
804 |
+
|
805 |
+
self.output_dose(
|
806 |
+
"Breast diameter: ",
|
807 |
+
breast_diameter,
|
808 |
+
"Breast_glandularity: ",
|
809 |
+
breast_glandularity,
|
810 |
+
"Breast Height: ",
|
811 |
+
self.Breast_height_combo.get(),
|
812 |
+
)
|
813 |
+
|
814 |
+
except ValueError: # error in air kerma inputs
|
815 |
+
pop_up = customtkinter.CTkToplevel()
|
816 |
+
|
817 |
+
if air_kerma_check == 0:
|
818 |
+
customtkinter.CTkLabel(
|
819 |
+
pop_up,
|
820 |
+
text="Please enter a numeric value into the air kerma entry box or into \nthe number of projections box",
|
821 |
+
font=("Roman", font_size),
|
822 |
+
).pack()
|
823 |
+
|
824 |
+
else:
|
825 |
+
customtkinter.CTkLabel(
|
826 |
+
pop_up,
|
827 |
+
text="Please enter only numbers into the air kerma and ensure \nthat a numeric value is placed into the number of projections",
|
828 |
+
font=("Roman", font_size),
|
829 |
+
).pack()
|
830 |
+
|
831 |
+
except TypeError: # error in incident spectrum
|
832 |
+
pop_up = customtkinter.CTkToplevel()
|
833 |
+
|
834 |
+
customtkinter.CTkLabel(
|
835 |
+
pop_up,
|
836 |
+
text="Please enter an incident spectrum",
|
837 |
+
font=("Roman", font_size),
|
838 |
+
).pack()
|
839 |
+
|
840 |
+
|
841 |
+
# %%% Executable Code
|
842 |
+
parser = argparse.ArgumentParser()
|
843 |
+
parser.add_argument(
|
844 |
+
"--font_size_set",
|
845 |
+
nargs="?",
|
846 |
+
default=1,
|
847 |
+
type=int,
|
848 |
+
help="select the font size set (default=1 is the first set)",
|
849 |
+
)
|
850 |
+
args = parser.parse_args()
|
851 |
+
font_size = dict_font_size_set[args.font_size_set]
|
852 |
+
font_size = dict_font_size_set[args.font_size_set]
|
853 |
+
|
854 |
+
customtkinter.set_appearance_mode("light")
|
855 |
+
root = customtkinter.CTk()
|
856 |
+
root.title("BCT Dose Calculator")
|
857 |
+
CT_dose = Main_Window(root)
|
858 |
+
root.protocol("WM_DELETE_WINDOW", quit_me)
|
859 |
+
root.mainloop()
|
PyBDC/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Python Breast Dosage Calculator: PyBDC
|
2 |
+
Python toolkit for calculating dosage for breast CT.\
|
3 |
+
The following software enables accurate dose estimation for one or various breast exposures specifically for breast CT. This tool is a GUI software that can be used on Windows, Mac, and Linux operating systems. The mode is further explained below along with an overview of the methods, how to choose a method, the program inputs and buttons, the incident spectrum format, images of the GUI, and the accompanying data files.
|
4 |
+
|
5 |
+
Code execution
|
6 |
+
----------
|
7 |
+
Clone PyBDC repository.
|
8 |
+
```
|
9 |
+
git clone https://github.com/harshamarupudi56/PyBDC.git
|
10 |
+
```
|
11 |
+
|
12 |
+
Run the following commands to install required dependencies.
|
13 |
+
```
|
14 |
+
apt-get -y install python3.11-tk
|
15 |
+
apt-get -y install pip
|
16 |
+
cd PyBDC
|
17 |
+
pip install -r requirements.txt
|
18 |
+
```
|
19 |
+
|
20 |
+
The required dependencies in [requirements.txt](requirements.txt).
|
21 |
+
```
|
22 |
+
customtkinter==5.2.2
|
23 |
+
matplotlib==3.8.0
|
24 |
+
numpy==1.26.0
|
25 |
+
pandas==1.3.4
|
26 |
+
```
|
27 |
+
|
28 |
+
Run PyBDC.
|
29 |
+
```
|
30 |
+
python3 PyBDC.py
|
31 |
+
```
|
32 |
+
|
33 |
+
PyBDC can also be run through its container available at https://huggingface.co/didsr/PyBDC-Container
|
34 |
+
|
35 |
+
User guide
|
36 |
+
----------
|
37 |
+
Please refer to the technical documentation https://pybdc.readthedocs.io/en/latest/
|
38 |
+
|
39 |
+
Disclaimer
|
40 |
+
----------
|
41 |
+
|
42 |
+
This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.
|
43 |
+
|
44 |
+
|
45 |
+
PyBDC: Harsha Marupudi, M.Eng., Joseph Manus B.S., Bahaa Ghammraoui, Ph.D. US Food and Drug Administration, Center for Devices and Radiological Health, Office of Science and Engineering Labs, Division of Imaging, Diagnostics, and Software Reliability.
|
46 |
+
|
47 |
+
|
48 |
+
|
49 |
+
|
50 |
+
References
|
51 |
+
----------
|
52 |
+
1. Sarno, A., Mettivier, G., Di Lillo, F., & Russo, P. (2017). A Monte Carlo study of monoenergetic and polyenergetic normalized glandular dose (DgN) coefficients in mammography. Physics in medicine and biology, 62(1), 306–325. https://doi.org/10.1088/1361-6560/62/1/306
|
53 |
+
2. Hernandez, A. M., Becker, A. E., & Boone, J. M. (2019). Updated breast CT dose coefficients (DgNCT ) using patient-derived breast shapes and heterogeneous fibroglandular distributions. Medical physics, 46(3), 1455–1466. https://doi.org/10.1002/mp.13391
|
54 |
+
3. Sechopoulos, I., Feng, S. S., & D'Orsi, C. J. (2010). Dosimetric characterization of a dedicated breast computed tomography clinical prototype. Medical physics, 37(8), 4110–4120. https://doi.org/10.1118/1.3457331
|
55 |
+
|
56 |
+
|
PyBDC/User_Guide.md
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Quick Start Guide for PyBDC 1.0
|
2 |
+
|
3 |
+
1. To begin start by choosing a method: Sarno Koning, Sarno Incident Spectrum, or Hernandez Heterogeneous BCT
|
4 |
+
|
5 |
+
1. Each method can be selected by selecting the radio button next to the method
|
6 |
+
|
7 |
+
1. the default is Sarno Incident Spectrum
|
8 |
+
|
9 |
+
2. Selecting the Sarno Koning BCT will lead to an output in the text box stating a description of Koning
|
10 |
+
BCT apparatus
|
11 |
+
|
12 |
+
3. Selecting the Hernandez Heterogeneous BCT method will lead to the text box on the bottom corner being
|
13 |
+
filled with the a description for each of the heterogeneous categories
|
14 |
+
|
15 |
+
2. After selecting a method, choose your parameters in the box next over
|
16 |
+
|
17 |
+
1. Sample parameters include breast diameter, breast height, etc.
|
18 |
+
|
19 |
+
2. Simply click on the downward arrow and choose the parameter of your choice
|
20 |
+
|
21 |
+
3. You'll notice some parameters are deactivated and this is due to the method of your choice. Each method
|
22 |
+
uses different sets of parameters. As such, the parameters necessary for the method will remain active
|
23 |
+
and those not necessary will remain inactive
|
24 |
+
|
25 |
+
3. After choosing parameters, enter your Air Kerma along with the input units and the desired output units. Air kerma is defined as the amount of energy deposited into the air when a photon passes through it. The number of projections should also
|
26 |
+
be added. This is defined as the number of individual X-ray measurements taken during the initial scan.
|
27 |
+
|
28 |
+
1. Simply enter your Air Kerma into the Air Kerma box and like before choose the input units in Air Kerma
|
29 |
+
Units and output units via MGD Units by pressing the downward arrow
|
30 |
+
|
31 |
+
4. Depending on the method of your choice, you will have the option to input an incident spectrum and graph that
|
32 |
+
spectrum
|
33 |
+
|
34 |
+
1. If you have chosen either Sarno Incident Spectrum or Hernandez Heterogeneous BCT, the option the input an
|
35 |
+
incident spectrum will be available to you.
|
36 |
+
|
37 |
+
1. This is not optional; you must enter an incident spectrum for the method to work
|
38 |
+
|
39 |
+
2. Simply press the Input Incident Spectrum Button and a popup will appear prompting you to choose a file.
|
40 |
+
Please select an appropriate text file following the format outlined in the complete user guide.
|
41 |
+
|
42 |
+
1. Once an acceptable file has been chosen, a shortened file name will appear in the text box found on
|
43 |
+
the bottom left
|
44 |
+
|
45 |
+
3. After inputting the file, the Graph Spectrum button will activate. You can then press the Graph Spectrum
|
46 |
+
button which will display your incident spectrum on the graph
|
47 |
+
|
48 |
+
5. Once you are satisfied with all your inputs, you can press the Calculate Dose button found at the bottom left corner
|
49 |
+
next to the Clear Text button
|
50 |
+
|
51 |
+
1. Pressing the Calculate Dose button will lead to an output in the text box of your mean glandular dose value
|
52 |
+
and your chosen parameters.
|
53 |
+
|
54 |
+
2. The text will remain in the box unless you elect to clear the box. The box can be easily cleared by pressing
|
55 |
+
the Clear Text button. Do note that your previous values will be cleared and cannot be retrieved.
|
56 |
+
|
57 |
+
6. [method_specific_inputs.toml](method_specific_inputs.toml) has method specific outputs given assumptions of homogenous or heterogenous composition
|
PyBDC/Verification.py
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
|
4 |
+
"""
|
5 |
+
Verification code using Sarno any spectrum for a breast with a diamter 16 cm, radius of 2xradius, and glandularity of 50%. Using the defined keV, I, and coefficients the normalized glandular dose can be computed. The correct value for these parameters
|
6 |
+
is 0.03614995451146596. The mean glandular dose was computed using the parameters of 300 projections, 0.5 mAs, and an input air kerma of 5 mR.
|
7 |
+
|
8 |
+
"""
|
9 |
+
|
10 |
+
import sys
|
11 |
+
import numpy as np
|
12 |
+
from dose_equations import (
|
13 |
+
Sarno_mono_dgn,
|
14 |
+
Sarno_poly_dgn,
|
15 |
+
sarno_dgnct,
|
16 |
+
Hernandez_hetero_mono_dgn,
|
17 |
+
exposure_per_fluence,
|
18 |
+
Sechopoulos_poly_dgn,
|
19 |
+
)
|
20 |
+
|
21 |
+
|
22 |
+
def exposure_per_fluence(E):
|
23 |
+
exposure = np.zeros(len(E))
|
24 |
+
for i in range(len(exposure)):
|
25 |
+
keV = E[i]
|
26 |
+
temp = (
|
27 |
+
(
|
28 |
+
(
|
29 |
+
-5.023290717769674e-6
|
30 |
+
+ 1.810595449064631e-7
|
31 |
+
+ np.sqrt(keV)
|
32 |
+
+ np.log(keV)
|
33 |
+
+ 0.008838658459816926 / keV**2
|
34 |
+
)
|
35 |
+
** (10**-3)
|
36 |
+
)
|
37 |
+
/ 1000
|
38 |
+
* 0.1145
|
39 |
+
)
|
40 |
+
exposure[i] = temp
|
41 |
+
return exposure
|
42 |
+
|
43 |
+
|
44 |
+
def dgn_calculate(a, b, c, d, e, f, g, h, keVs):
|
45 |
+
dgn = np.zeros(len(keVs))
|
46 |
+
for i in range(len(keVs)):
|
47 |
+
E = keVs[i]
|
48 |
+
temp = (
|
49 |
+
a * 10 ** (-14) * E**8
|
50 |
+
+ b * 10 ** (-12) * E**7
|
51 |
+
+ c * 10 ** (-10) * E**6
|
52 |
+
+ d * 10 ** (-8) * E**5
|
53 |
+
+ e * 10 ** (-6) * E**4
|
54 |
+
+ f * 10 ** (-4) * E**3
|
55 |
+
+ g * 10 ** (-3) * E**2
|
56 |
+
+ h * 10 ** (-2) * E
|
57 |
+
)
|
58 |
+
dgn[i] = temp
|
59 |
+
return dgn
|
60 |
+
|
61 |
+
|
62 |
+
def pDgN_calculate_denominator(I, exposure):
|
63 |
+
total = I * exposure
|
64 |
+
pDgN_denom = np.sum(total)
|
65 |
+
|
66 |
+
return pDgN_denom
|
67 |
+
|
68 |
+
|
69 |
+
def pDgN_calculate_numerator(I, dgn, exposure):
|
70 |
+
total = I * exposure * dgn
|
71 |
+
pDgN_num = sum(total)
|
72 |
+
return pDgN_num
|
73 |
+
|
74 |
+
|
75 |
+
def calculate_pDgNct(*values):
|
76 |
+
keV = values[2]
|
77 |
+
I = values[3]
|
78 |
+
psiE = np.array(list(map(exposure_per_fluence, keV)))
|
79 |
+
|
80 |
+
if values[0] == "Sarno Koning":
|
81 |
+
variables = values[1]
|
82 |
+
DgNctE = np.array(
|
83 |
+
list(
|
84 |
+
map(
|
85 |
+
sarno_dgnct,
|
86 |
+
variables[:, 0],
|
87 |
+
variables[:, 1],
|
88 |
+
variables[:, 2],
|
89 |
+
variables[:, 3],
|
90 |
+
variables[:, 4],
|
91 |
+
variables[:, 5],
|
92 |
+
variables[:, 6],
|
93 |
+
variables[:, 7],
|
94 |
+
keV,
|
95 |
+
)
|
96 |
+
)
|
97 |
+
)
|
98 |
+
pDgN = np.sum(I * psiE * DgNctE) / np.sum(I * psiE)
|
99 |
+
elif values[0] == "Hernandez":
|
100 |
+
DgN_list = np.array(values[1])
|
101 |
+
pDgN = np.sum(I * psiE * DgN_list) / (np.sum(I * psiE))
|
102 |
+
|
103 |
+
return pDgN
|
104 |
+
|
105 |
+
|
106 |
+
# calculate mgd input air kerma for 1 projection
|
107 |
+
def calculate_mgd(
|
108 |
+
air_KERMA, dgn, number_of_projections, mAs, air_KERMA_input_units, output_units
|
109 |
+
):
|
110 |
+
# Convert air kerma input to mGy if it is not already in mGy
|
111 |
+
if air_KERMA_input_units != "mGy":
|
112 |
+
if air_KERMA_input_units == "mrad":
|
113 |
+
air_KERMA = air_KERMA * 0.01 # convert from mrad air kerma to mGy
|
114 |
+
elif air_KERMA_input_units == "R":
|
115 |
+
air_KERMA = air_KERMA * 8.77 # convert from R to mGy
|
116 |
+
elif air_KERMA_input_units == "mR":
|
117 |
+
air_KERMA = air_KERMA * 0.00877 # convert from mR to mGy
|
118 |
+
|
119 |
+
# Calculate MGD in mGy/mGy
|
120 |
+
mgd = air_KERMA * dgn * float(number_of_projections) * mAs
|
121 |
+
|
122 |
+
# Convert MGD to mrad if output units are mrad
|
123 |
+
if output_units == "mrad":
|
124 |
+
mgd = mgd * 100 # converts mgd to mrad
|
125 |
+
|
126 |
+
return mgd
|
127 |
+
|
128 |
+
|
129 |
+
a = -0.41324119391158
|
130 |
+
b = 4.88540710576677
|
131 |
+
c = -13.0460380815292
|
132 |
+
d = 15.3913804609064
|
133 |
+
e = -9.19621868949206
|
134 |
+
f = 2.66123817129083
|
135 |
+
g = -2.67974610124986
|
136 |
+
h = 0.883219836298924
|
137 |
+
|
138 |
+
air_KERMA = 5.0 # mR
|
139 |
+
number_of_projections = 300
|
140 |
+
mAs = 0.5
|
141 |
+
|
142 |
+
keV = np.array([10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14])
|
143 |
+
I = np.array(
|
144 |
+
[
|
145 |
+
6.20275e2,
|
146 |
+
2.26229e2,
|
147 |
+
5.25667e2,
|
148 |
+
2.39324e3,
|
149 |
+
1.45979e3,
|
150 |
+
2.17293e3,
|
151 |
+
3.36611e3,
|
152 |
+
4.89394e3,
|
153 |
+
6.61405e3,
|
154 |
+
]
|
155 |
+
)
|
156 |
+
|
157 |
+
exposure = exposure_per_fluence(keV)
|
158 |
+
dgn = dgn_calculate(a, b, c, d, e, f, g, h, keV)
|
159 |
+
|
160 |
+
pDgN_num = pDgN_calculate_numerator(I, dgn, exposure)
|
161 |
+
pDgN_denom = pDgN_calculate_denominator(I, exposure)
|
162 |
+
pDgN = pDgN_num / pDgN_denom
|
163 |
+
|
164 |
+
print("pDgN =", pDgN)
|
165 |
+
|
166 |
+
mgd = calculate_mgd(air_KERMA, pDgN, number_of_projections, mAs, "mR", "mGy")
|
167 |
+
|
168 |
+
print("mgd =", mgd)
|
PyBDC/dose_equations.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
Created on Tue Dec 13 14:54:18 2022
|
5 |
+
|
6 |
+
Equations and dgn values for tkinter
|
7 |
+
|
8 |
+
@author: DIDSR
|
9 |
+
"""
|
10 |
+
|
11 |
+
import numpy as np
|
12 |
+
import pandas as pd
|
13 |
+
|
14 |
+
import os
|
15 |
+
|
16 |
+
# Sarno polyenergetic and monoenergetic tables from published papers
|
17 |
+
Sarno_mono_dgn = pd.read_csv(
|
18 |
+
os.path.join(os.getcwd(), "dose_table", "Sarno_mono_dgn.txt"), sep=" "
|
19 |
+
)
|
20 |
+
|
21 |
+
Sarno_poly_dgn = pd.read_csv(
|
22 |
+
os.path.join(os.getcwd(), "dose_table", "Sarno_poly_dgn.txt"),
|
23 |
+
sep=" ",
|
24 |
+
index_col="HVL",
|
25 |
+
)
|
26 |
+
|
27 |
+
# monoenergetic dgnct equation 8th degree polynomial fitting
|
28 |
+
sarno_dgnct = (
|
29 |
+
lambda a, b, c, d, e, f, g, h, E: (a * 10**-14) * E**8
|
30 |
+
+ (b * 10**-12) * E**7
|
31 |
+
+ (c * 10**-10) * E**6
|
32 |
+
+ (d * 10**-8) * E**5
|
33 |
+
+ (e * 10**-6) * E**4
|
34 |
+
+ (f * 10**-4) * E**3
|
35 |
+
+ (g * 10**-3) * E**2
|
36 |
+
+ (h * 10**-2) * E
|
37 |
+
)
|
38 |
+
# define equation for exposure per fluence
|
39 |
+
aa = -5.023290717769674e-6
|
40 |
+
bb = 1.810595449064631e-7
|
41 |
+
cc = 0.008838658459816926
|
42 |
+
exposure_per_fluence = (
|
43 |
+
lambda E: (aa + bb * np.log(E) * np.log(E) + cc / E**2) ** (-1) / 1000 * 0.1145
|
44 |
+
)
|
45 |
+
|
46 |
+
# Hernandez_hetero_dgn table
|
47 |
+
Hernandez_hetero_mono_dgn = pd.read_csv(
|
48 |
+
os.path.join(os.getcwd(), "dose_table", "Hernandez_heterogeneous_dgn.txt"),
|
49 |
+
sep=",",
|
50 |
+
header=0,
|
51 |
+
)
|
52 |
+
|
53 |
+
# Sechopoulos dgn
|
54 |
+
Sechopoulos_poly_dgn = pd.read_csv(
|
55 |
+
os.path.join(os.getcwd(), "dose_table", "Sechopoulos_dgn.txt"),
|
56 |
+
sep=" ",
|
57 |
+
header=None,
|
58 |
+
index_col=0,
|
59 |
+
) # index is diameter at chest wall (breast diameter)
|
60 |
+
Sechopoulos_poly_dgn.columns = [
|
61 |
+
"Chest wall-to-nipple distance",
|
62 |
+
"1%",
|
63 |
+
"14.3%",
|
64 |
+
"25%",
|
65 |
+
"50%",
|
66 |
+
"75%",
|
67 |
+
"100%",
|
68 |
+
]
|
PyBDC/dose_table/Hernandez_heterogeneous_dgn.txt
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Photon Energy,V1,V3,V5
|
2 |
+
9,0.00083583,2.6404e-05,0.00041403
|
3 |
+
10,0.0021143,0.00011412,0.00077867
|
4 |
+
11,0.0047645,0.00042776,0.0015428
|
5 |
+
12,0.0097646,0.0014649,0.0029913
|
6 |
+
13,0.01824,0.0041467,0.0058035
|
7 |
+
14,0.031113,0.0097186,0.010832
|
8 |
+
15,0.049135,0.01983,0.019086
|
9 |
+
16,0.072678,0.035183,0.031512
|
10 |
+
17,0.10108,0.056164,0.048909
|
11 |
+
18,0.13452,0.083415,0.071591
|
12 |
+
19,0.1708,0.1159,0.098474
|
13 |
+
20,0.20919,0.15217,0.12885
|
14 |
+
21,0.24939,0.19137,0.16349
|
15 |
+
22,0.29167,0.23385,0.20084
|
16 |
+
23,0.33322,0.27748,0.24088
|
17 |
+
24,0.37348,0.32097,0.28171
|
18 |
+
25,0.41337,0.3639,0.32233
|
19 |
+
26,0.45222,0.4078,0.36434
|
20 |
+
27,0.48875,0.45082,0.40399
|
21 |
+
28,0.52471,0.48937,0.44384
|
22 |
+
29,0.55386,0.52752,0.48112
|
23 |
+
30,0.58406,0.56409,0.51679
|
24 |
+
31,0.61198,0.59943,0.55391
|
25 |
+
32,0.63962,0.63189,0.58705
|
26 |
+
33,0.66629,0.66392,0.61871
|
27 |
+
34,0.69148,0.6944,0.65311
|
28 |
+
35,0.71432,0.71936,0.68272
|
29 |
+
36,0.73564,0.74955,0.71284
|
30 |
+
37,0.7574,0.77381,0.73847
|
31 |
+
38,0.77718,0.7986,0.76403
|
32 |
+
39,0.79363,0.81897,0.78669
|
33 |
+
40,0.81075,0.83792,0.80639
|
34 |
+
41,0.82391,0.85488,0.82719
|
35 |
+
42,0.83935,0.87258,0.84885
|
36 |
+
43,0.84975,0.88682,0.86454
|
37 |
+
44,0.86338,0.90121,0.88299
|
38 |
+
45,0.8771,0.91859,0.90091
|
39 |
+
46,0.8857,0.93117,0.91449
|
40 |
+
47,0.89767,0.94599,0.92882
|
41 |
+
48,0.90676,0.95653,0.94479
|
42 |
+
49,0.91719,0.9684,0.95507
|
43 |
+
50,0.9253,0.98087,0.96429
|
44 |
+
51,0.93172,0.9872,0.97324
|
45 |
+
52,0.9368,0.99436,0.98302
|
46 |
+
53,0.9457,1.0031,0.99217
|
47 |
+
54,0.95372,1.0111,1.0018
|
48 |
+
55,0.95872,1.0143,1.0076
|
49 |
+
56,0.96344,1.0203,1.0153
|
50 |
+
57,0.9704,1.0285,1.0216
|
51 |
+
58,0.97136,1.0334,1.0247
|
52 |
+
59,0.97525,1.0335,1.0254
|
53 |
+
60,0.97436,1.0337,1.0287
|
54 |
+
61,0.9734,1.0338,1.0298
|
55 |
+
62,0.9747,1.0356,1.0265
|
56 |
+
63,0.97796,1.0383,1.0298
|
57 |
+
64,0.97861,1.0382,1.0331
|
58 |
+
65,0.98172,1.037,1.0309
|
59 |
+
66,0.98315,1.0392,1.0363
|
60 |
+
67,0.98622,1.0408,1.0401
|
61 |
+
68,0.9875,1.0402,1.0402
|
62 |
+
69,0.98744,1.0412,1.0393
|
63 |
+
70,0.99011,1.0423,1.0394
|
PyBDC/dose_table/Sarno_mono_dgn.txt
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
8 10 12 14 16 18 Glandularity "breast height"
|
2 |
+
-20.5892189574262 -16.2549875815176 -13.0105252240121 -8.69823775324488 -6.2626374180787 -4.11905486084258 0.1% 1x
|
3 |
+
73.1896769700967 58.9667571016743 48.2473118933221 33.7059595402125 25.2453958389843 17.607318355718 0.1% 1x
|
4 |
+
-106.257384254468 -87.6793954179481 -73.5109692475839 -53.6746702293416 -41.7447427763885 -30.6679485592535 0.1% 1x
|
5 |
+
80.2630529832939 68.1574607426119 58.7507718113977 44.8431928067761 36.1746085960411 27.852800959409 0.1% 1x
|
6 |
+
-32.9588597556987 -29.0022142048811 -25.8364371052747 -20.6148436051423 -17.2415925802501 -13.8531069455155 0.1% 1x
|
7 |
+
6.80939523347842 6.28437360736677 5.84159353470471 4.8660681546934 4.21785343604026 3.51504057484829 0.1% 1x
|
8 |
+
-5.10495486459641 -5.12103368116827 -5.11264758335616 -4.40730096137731 -3.94413870954404 -3.34153429589538 0.1% 1x
|
9 |
+
1.16791414363473 1.32805221986491 1.48251939370311 1.32767184556531 1.23707123663961 1.0630020174972 0.1% 1x
|
10 |
+
-18.8614633901972 -14.4873821970602 -10.2748774672606 -6.78097602091439 -4.13790052150762 -2.42034880680238 14.3% 1x
|
11 |
+
67.9966324124675 53.051921818743 39.1167547568082 27.1740161529563 17.8421648486217 11.6054724812263 14.3% 1x
|
12 |
+
-100.407920059751 -79.7473049402957 -61.2089746714773 -44.6288811500868 -31.2618830095452 -22.0128547562243 14.3% 1x
|
13 |
+
77.4646880984559 62.7877857350058 50.2583040410241 38.3812938657821 28.4970859206457 21.3667008430265 14.3% 1x
|
14 |
+
-32.7118714494535 -27.1316880770574 -22.7142258479208 -18.1428642950792 -14.1994217090572 -11.2098957904762 14.3% 1x
|
15 |
+
7.05148339891376 5.99583796759882 5.27779613294281 4.40051727688339 3.6052960442998 2.96427653092378 14.3% 1x
|
16 |
+
-5.8124256458628 -5.03917259213266 -4.73697579359378 -4.08636716334962 -3.43716045376484 -2.86390931824229 14.3% 1x
|
17 |
+
1.52100591467739 1.36870948902565 1.41534753702737 1.26955853801553 1.09732746342247 0.91873965627105 14.3% 1x
|
18 |
+
-16.8109585387878 -13.4465156748677 -9.68833762741007 -6.11601383659056 -2.92884201402284 -1.53088670677826 25% 1x
|
19 |
+
61.3203591886266 49.7095250445647 36.9239879441541 24.6505665685653 13.5410368798031 8.3108080532326 25% 1x
|
20 |
+
-91.6911532064717 -75.4763433076621 -57.9584838150434 -40.8387218553826 -25.0348913031681 -17.0693179966546 25% 1x
|
21 |
+
71.6959740699239 60.0841512514733 47.8600943957251 35.531212234849 23.828597628169 17.5426167439385 25% 1x
|
22 |
+
-30.7168317330683 -26.3004505311856 -21.8254023885068 -17.0415200305136 -12.3041451569027 -9.61554981309142 25% 1x
|
23 |
+
6.72567964692271 5.91091438532735 5.14127031813 4.20804051821994 3.21372277739241 2.62809073905998 25% 1x
|
24 |
+
-5.63828047974027 -5.11810659952038 -4.72745621155995 -4.004296872229 -3.10100905160595 -2.57337899355731 25% 1x
|
25 |
+
1.50003590490319 1.45160407675241 1.46418012347419 1.28725871761359 0.996805062601169 0.832057685964819 25% 1x
|
26 |
+
-14.4194331182086 -10.8013579981451 -6.67686602053368 -3.11421837779407 -1.22498409810941 0.61754643044812 50% 1x
|
27 |
+
53.0306863858881 40.7664766098944 26.5964760912995 14.064290973413 7.18311145227733 0.63986401441522 50% 1x
|
28 |
+
-80.0309463075534 -63.3428246480193 -43.6147787221285 -25.6397183986664 -15.3938194860164 -5.85258938919576 50% 1x
|
29 |
+
63.2268264701365 51.7603488938994 37.6221703887495 24.220214659282 16.2748654253439 8.98151812732922 50% 1x
|
30 |
+
-27.392640232255 -23.3534316236867 -17.9249758239639 -12.4734711979282 -9.11208621648777 -6.04156955084438 50% 1x
|
31 |
+
6.06179050145871 5.44477936882484 4.41096349260873 3.26463727780154 2.53337970511689 1.8589587987115 50% 1x
|
32 |
+
-5.09150623907318 -4.97005206070813 -4.22456914511412 -3.18593036465252 -2.51531508838942 -1.87490493956134 50% 1x
|
33 |
+
1.37869788875488 1.51816787446659 1.37145898722699 1.03904920464228 0.82404206681742 0.60958394158242 50% 1x
|
34 |
+
-10.1369427582467 -5.63727868846832 -0.88311260146176 1.3795739987699 2.20432277915504 3.13772472668648 100% 1x
|
35 |
+
38.4916378213188 22.8313076887658 6.42256273905311 -1.91415256450575 -5.27730445856237 -8.85706254067506 100% 1x
|
36 |
+
-60.268970721968 -38.0934542891817 -14.9728122886743 -2.39054694621721 3.17566459288785 8.8141166190236 100% 1x
|
37 |
+
49.7035461656967 33.4640292295369 16.4885254072397 6.57088059398393 1.80601760172866 -2.84985255659296 100% 1x
|
38 |
+
-22.6653251627581 -16.2521610655177 -9.42615905692364 -5.14067240355409 -2.931935421163 -0.81563772315493 100% 1x
|
39 |
+
5.34921612065528 4.07667335668397 2.6501127782798 1.68787028401425 1.16685383674954 0.66637150773542 100% 1x
|
40 |
+
-4.95938165842527 -3.95923738240158 -2.66824289994019 -1.73234383603109 -1.22630669106474 -0.72087477313467 100% 1x
|
41 |
+
1.54193691681923 1.28936502049872 0.88710294094141 0.56677661922357 0.39681132630782 0.21888243481137 100% 1x
|
42 |
+
-19.1645671809949 -16.8147836393425 -11.2842175549556 -7.36010377719434 -4.57868618758555 -2.47868929641614 0.1% 1.5x
|
43 |
+
69.1642550506839 61.2714924441808 42.9395827146565 29.4256514966446 19.6579289087392 11.9981028018794 0.1% 1.5x
|
44 |
+
-101.965119136956 -91.6144471733953 -67.1718980141002 -48.3350823642992 -34.3571345072815 -22.9686778874197 0.1% 1.5x
|
45 |
+
78.2354620498176 71.7362807421884 55.1555652655511 41.6575332103183 31.2933265356589 22.5028832092703 0.1% 1.5x
|
46 |
+
-32.6441079147333 -30.8365367945318 -24.9383780491408 -19.7612508863289 -15.6064942173144 -11.9172614942877 0.1% 1.5x
|
47 |
+
6.85235717685667 6.78822530725787 5.79998592988430 4.81380972545511 3.97289833000403 3.17917768091892 0.1% 1.5x
|
48 |
+
-5.20255134178982 -5.72186953226948 -5.21751943901165 -4.49305343499093 -3.80832311270289 -3.08782804193953 0.1% 1.5x
|
49 |
+
1.19982076353667 1.56076060188167 1.56492881077813 1.40461534333983 1.22337348295479 0.99454595304800 0.1% 1.5x
|
50 |
+
-18.9368374169727 -14.2466856768054 -9.67658919212705 -5.83550670894167 -3.17399694212437 -0.58313311347465 14.3% 1.5x
|
51 |
+
68.1975916819477 52.7885545642611 37.3521099989829 24.0144522955238 14.4152951488294 5.37200133816344 14.3% 1.5x
|
52 |
+
-100.584799434600 -80.3481396379044 -59.3364845238459 -40.5256897723847 -26.4182683111730 -13.4764271582640 14.3% 1.5x
|
53 |
+
77.4683655140414 64.1380253288522 49.5508760618772 35.8474373511219 25.0842774943437 15.3944811970640 14.3% 1.5x
|
54 |
+
-32.6054812956868 -28.1650488977722 -22.8333936929596 -17.4504776200432 -12.9832144755277 -8.99760803321632 14.3% 1.5x
|
55 |
+
6.96791822084179 6.35507060426797 5.42897605516953 4.36315569635605 3.41068862131482 2.55787568692749 14.3% 1.5x
|
56 |
+
-5.55480011203282 -5.53744406808503 -5.02555151475395 -4.17552960525184 -3.31257426365004 -2.52428449248738 14.3% 1.5x
|
57 |
+
1.38818732958602 1.58680153397930 1.56543387188259 1.34653090032133 1.07202357452204 0.81469244777539 14.3% 1.5x
|
58 |
+
-17.1884488866233 -12.4648977730464 -7.86447485868652 -4.26857559197584 -1.59017706091734 0.33534587896044 25% 1.5x
|
59 |
+
62.6110514618001 46.8351785403993 31.0816414513323 18.5353908511224 8.96204984806396 1.94796923562449 25% 1.5x
|
60 |
+
-93.4549995471558 -72.3737978055242 -50.5591679805397 -32.7364823535155 -18.7564942690574 -8.26799153644478 25% 1.5x
|
61 |
+
72.9082591782242 58.7281602761448 43.2352293155123 30.1173389665102 19.4879066305298 11.2810730591863 25% 1.5x
|
62 |
+
-31.1311975822105 -26.2535622724901 -20.3962428657680 -15.1685102551698 -10.7570129309277 -7.23294941203410 25% 1.5x
|
63 |
+
6.76954513778785 6.04121564868853 4.95723130361156 3.90023164701591 2.95603290328365 2.17053554755444 25% 1.5x
|
64 |
+
-5.54329792737660 -5.38824302422911 -4.65680239689631 -3.78329792777939 -2.92101412636709 -2.16681828800954 25% 1.5x
|
65 |
+
1.44343752532824 1.58994822097885 1.46794142071639 1.23092057141398 0.95398101969790 0.69923122392582 25% 1.5x
|
66 |
+
-15.1880781026812 -9.41627204366998 -4.86316066577117 -1.90660502160902 0.800916034431646 2.20897796113271 50% 1.5x
|
67 |
+
55.8853162629730 36.4768579416517 20.6104067446398 10.0460003667955 0.222936691687627 -4.99674714943268 50% 1.5x
|
68 |
+
-84.4950820333717 -58.1819978050464 -35.7045638888039 -20.2855203226159 -5.71448741769510 2.25268262092014 50% 1.5x
|
69 |
+
67.0207373868516 48.8178052252957 32.3448679025270 20.6381923159504 9.35813357471496 2.97361078801558 50% 1.5x
|
70 |
+
-29.2560945234631 -22.6244423618499 -16.0962713530783 -11.2553171293301 -6.46242636201031 -3.64639846320904 50% 1.5x
|
71 |
+
6.56732896400909 5.41934758149813 4.10705395092666 3.07980853984166 2.01643120903275 1.37126471303537 50% 1.5x
|
72 |
+
-5.71161373701105 -5.08117559441464 -3.99860089133949 -3.07983057699189 -2.04287106983903 -1.41142550858313 50% 1.5x
|
73 |
+
1.62883231176140 1.60555739426190 1.31021175203602 1.02309697001406 0.665251808238488 0.448949271362092 50% 1.5x
|
74 |
+
-9.08985806284783 -4.24472253222862 -0.76984500543629 1.79755857225210 3.86063705017426 3.61533168777020 100% 1.5x
|
75 |
+
35.1556369384749 18.1509079784559 5.68125150161062 -3.63463909599484 -11.0205284735661 -10.7181951668970 100% 1.5x
|
76 |
+
-56.0978712690103 -31.8072030795209 -13.4899048502527 0.37105862852171 11.2896086675581 11.7593837388993 100% 1.5x
|
77 |
+
47.1824896624291 29.2211378862523 15.1812213039088 4.38409501074898 -4.13536381059572 -5.23682533548250 100% 1.5x
|
78 |
+
-21.9600453686823 -14.7826330542632 -8.89402113581299 -4.26541028396866 -0.57333179461705 0.20490475866474 100% 1.5x
|
79 |
+
5.29110896452988 3.84173121313000 2.56370945818317 1.52747236803440 0.68342584907207 0.45306012392519 100% 1.5x
|
80 |
+
-4.99601003982595 -3.81155649463395 -2.61967825700806 -1.60906764897764 -0.75979279134353 -0.52275565616072 100% 1.5x
|
81 |
+
1.58931930382548 1.27244560068908 0.88101681882966 0.53367982394117 0.23266989613221 0.15329649678692 100% 1.5x
|
82 |
+
-20.3453500911976 -15.3818577673824 -10.2085381494137 -5.82733246008717 -2.78095953625346 -1.00389834939120 0.1% 2x
|
83 |
+
73.2554361668989 56.8975786879096 39.4790873074193 24.4770521135583 13.5516022229364 6.99553918152219 0.1% 2x
|
84 |
+
-107.907465783956 -86.3983958268832 -62.7696059405248 -41.9387164948392 -25.9817373190385 -16.0778723477594 0.1% 2x
|
85 |
+
82.8941858466593 68.7388013299305 52.3929631099517 37.4873989211601 25.4008522980169 17.6058512760968 0.1% 2x
|
86 |
+
-34.7383808303456 -30.0397325611327 -24.0835770063152 -18.3565316136584 -13.3842908993097 -10.0427005745298 0.1% 2x
|
87 |
+
7.37059912539802 6.72678820985405 5.69120903653127 4.59330932164656 3.54545622880765 2.81284017168739 0.1% 2x
|
88 |
+
-5.79085861396574 -5.77337642017993 -5.18014471288083 -4.36215752364718 -3.42862300765967 -2.76054480158645 0.1% 2x
|
89 |
+
1.42058778605767 1.61983265007594 1.56888397920142 1.39101720599815 1.09953698599335 0.88760904291828 0.1% 2x
|
90 |
+
-19.1170265427664 -13.3058327996024 -8.35415941456442 -4.32615232196170 -1.49402451660712 0.92582907692514 14.3% 2x
|
91 |
+
69.0682816801379 49.8512852808101 33.0164364994159 19.0260534814189 8.87201415208120 0.22795992937770 14.3% 2x
|
92 |
+
-102.273279944056 -76.8017166510144 -53.6738836474383 -33.8699323355993 -19.0072269586949 -6.35662104463300 14.3% 2x
|
93 |
+
79.1707537558980 62.1205210589987 45.8434996421431 31.3032852217140 19.9876960727833 10.3055289159243 14.3% 2x
|
94 |
+
-33.5531941732455 -27.6710886601089 -21.5879390791509 -15.7999411755434 -11.1043742252699 -7.03216813741396 14.3% 2x
|
95 |
+
7.24589514523948 6.33987779688810 5.23439691510269 4.06255248392697 3.06013445568943 2.16764654523321 14.3% 2x
|
96 |
+
-5.90694530032777 -5.61697437182332 -4.90249004225999 -3.92493786069026 -3.01592608192114 -2.16739081871729 14.3% 2x
|
97 |
+
1.53372047301056 1.64617724031139 1.54078564885475 1.26945781266833 0.98029000820539 0.69537688160476 14.3% 2x
|
98 |
+
-17.7151618872944 -11.6762048587017 -6.83745246835591 -2.90772507473843 -0.00419777322261 1.31047973560291 25% 2x
|
99 |
+
64.5369249289555 44.4778685756716 27.8004533042877 13.9526793178979 3.54650464094095 -1.45485333819163 25% 2x
|
100 |
+
-96.4580997536959 -69.6893797342646 -46.3956009946817 -26.5054598331460 -11.2558621390243 -3.44916912000035 25% 2x
|
101 |
+
75.4750033870382 57.3560133542242 40.6176184430994 25.7822935056240 14.1278292266742 7.76486282215846 25% 2x
|
102 |
+
-32.4016083956099 -26.0210770204408 -19.5854473368220 -13.5637597038356 -8.68766438071822 -5.85550080302071 25% 2x
|
103 |
+
7.11588245353662 6.08362435654798 4.85856066823430 3.60217344742505 2.54429602167510 1.89745882642963 25% 2x
|
104 |
+
-5.97146437712964 -5.53397984775321 -4.64693238651176 -3.53068332340179 -2.53948610150421 -1.92285998024494 25% 2x
|
105 |
+
1.62192409374839 1.68095232949207 1.50086947203183 1.15229206241631 0.824476989727103 0.620000821622919 25% 2x
|
106 |
+
-13.7459716968014 -8.56380090371856 -4.28979969759713 -0.41324119391158 1.69230593550597 3.12544003276511 50% 2x
|
107 |
+
51.3376932532365 33.5719543961296 18.5529027571888 4.88540710576677 -2.88906422288599 -8.20020118784173 50% 2x
|
108 |
+
-78.7924495926802 -54.2608149912678 -32.7829108215061 -13.0460380815292 -1.28533369822837 6.83585315159465 50% 2x
|
109 |
+
63.4438541963516 46.1872198129110 30.2860417495202 15.3913804609064 6.09630272285736 -0.43863485493705 50% 2x
|
110 |
+
-28.1067595151831 -21.7329803636913 -15.3666388517613 -9.19621868949206 -5.16812566573774 -2.26596700372391 50% 2x
|
111 |
+
6.39451896430322 5.28357128464266 3.99295077756319 2.66123817129083 1.75541962408278 1.08403562001326 50% 2x
|
112 |
+
-5.59927627057295 -5.00124388885343 -3.93535686016687 -2.67974610124986 -1.80301650295393 -1.13828192939998 50% 2x
|
113 |
+
1.60310974735945 1.59173238124724 1.30285446626893 0.883219836298924 0.585083299976351 0.354872662135623 50% 2x
|
114 |
+
|
115 |
+
8.19501354358143 -3.43233929966256 1.06854465027246 2.69788034635764 3.99696833004187 3.61541032645446 100% 2x
|
116 |
+
32.3339621213143 15.4258208938566 -0.46194442378509 -6.80072235828109 -11.7370374938090 -10.9518596915828 100% 2x
|
117 |
+
-52.5743897761552 -28.1495435012571 -5.14993172462760 4.91883675862664 12.6606188617394 12.4397898399456 100% 2x
|
118 |
+
45.0099868190053 26.7488349477012 9.31794639978741 0.99324724634839 -5.39867149276577 -5.99288165168819 100% 2x
|
119 |
+
-21.3014430876912 -13.9225108347228 -6.65074765969073 -2.89482853763288 0.019070454024008 0.59618625122408 100% 2x
|
120 |
+
5.21105850309460 3.70302309527900 2.11518866240840 1.24232141816806 0.550066476635071 0.36163013483674 100% 2x
|
121 |
+
-4.97500545277725 -3.72233756306733 -2.19384386035287 -1.33366860960407 -0.63011980792665 -0.43734635307982 100% 2x
|
122 |
+
1.59722116812876 1.25463523341077 0.73278989126218 0.43715460733195 0.188038328621894 0.12613288060321 100% 2x
|
PyBDC/dose_table/Sarno_poly_dgn.txt
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
HVL 8 10 12 14 16 18 Glandularity "breast height"
|
2 |
+
1.25 0.509 0.464 0.426 0.394 0.367 0.343 0.1% 1x
|
3 |
+
1.30 0.518 0.473 0.435 0.403 0.375 0.352 0.1% 1x
|
4 |
+
1.35 0.528 0.483 0.445 0.412 0.384 0.36 0.1% 1x
|
5 |
+
1.40 0.537 0.492 0.454 0.421 0.393 0.369 0.1% 1x
|
6 |
+
1.45 0.546 0.501 0.463 0.429 0.401 0.377 0.1% 1x
|
7 |
+
1.50 0.554 0.509 0.471 0.437 0.409 0.384 0.1% 1x
|
8 |
+
1.25 0.49 0.444 0.406 0.374 0.347 0.324 14.3% 1x
|
9 |
+
1.30 0.5 0.454 0.415 0.383 0.356 0.333 14.3% 1x
|
10 |
+
1.35 0.51 0.463 0.425 0.392 0.365 0.341 14.3% 1x
|
11 |
+
1.40 0.519 0.473 0.433 0.401 0.373 0.349 14.3% 1x
|
12 |
+
1.45 0.528 0.481 0.442 0.409 0.381 0.357 14.3% 1x
|
13 |
+
1.50 0.536 0.489 0.45 0.417 0.388 0.364 14.3% 1x
|
14 |
+
1.25 0.479 0.432 0.393 0.361 0.335 0.312 25% 1x
|
15 |
+
1.30 0.488 0.441 0.402 0.37 0.343 0.32 25% 1x
|
16 |
+
1.35 0.498 0.451 0.412 0.379 0.352 0.329 25% 1x
|
17 |
+
1.40 0.508 0.46 0.42 0.388 0.36 0.336 25% 1x
|
18 |
+
1.45 0.516 0.468 0.429 0.396 0.368 0.344 25% 1x
|
19 |
+
1.50 0.525 0.477 0.437 0.404 0.375 0.351 25% 1x
|
20 |
+
1.25 0.45 0.402 0.364 0.333 0.307 0.285 50% 1x
|
21 |
+
1.30 0.46 0.411 0.373 0.341 0.315 0.293 50% 1x
|
22 |
+
1.35 0.47 0.421 0.382 0.35 0.323 0.301 50% 1x
|
23 |
+
1.40 0.479 0.43 0.391 0.358 0.331 0.308 50% 1x
|
24 |
+
1.45 0.488 0.438 0.399 0.366 0.338 0.315 50% 1x
|
25 |
+
1.50 0.496 0.446 0.407 0.373 0.346 0.322 50% 1x
|
26 |
+
1.25 0.397 0.35 0.314 0.284 0.26 0.24 100% 1x
|
27 |
+
1.30 0.406 0.359 0.322 0.292 0.267 0.247 100% 1x
|
28 |
+
1.35 0.416 0.368 0.33 0.299 0.274 0.253 100% 1x
|
29 |
+
1.40 0.425 0.377 0.338 0.307 0.281 0.26 100% 1x
|
30 |
+
1.45 0.433 0.385 0.346 0.314 0.288 0.267 100% 1x
|
31 |
+
1.50 0.441 0.392 0.353 0.321 0.295 0.273 100% 1x
|
32 |
+
1.25 0.532 0.486 0.445 0.411 0.381 0.355 0.1% 1.5x
|
33 |
+
1.30 0.542 0.496 0.455 0.421 0.391 0.364 0.1% 1.5x
|
34 |
+
1.35 0.553 0.507 0.465 0.431 0.4 0.374 0.1% 1.5x
|
35 |
+
1.40 0.563 0.517 0.475 0.44 0.41 0.383 0.1% 1.5x
|
36 |
+
1.45 0.572 0.526 0.484 0.449 0.418 0.391 0.1% 1.5x
|
37 |
+
1.50 0.581 0.535 0.493 0.458 0.427 0.399 0.1% 1.5x
|
38 |
+
1.25 0.511 0.464 0.423 0.389 0.36 0.335 14.3% 1.5x
|
39 |
+
1.30 0.521 0.474 0.433 0.399 0.369 0.344 14.3% 1.5x
|
40 |
+
1.35 0.532 0.484 0.443 0.409 0.379 0.353 14.3% 1.5x
|
41 |
+
1.40 0.542 0.494 0.453 0.418 0.388 0.361 14.3% 1.5x
|
42 |
+
1.45 0.551 0.504 0.462 0.427 0.396 0.369 14.3% 1.5x
|
43 |
+
1.50 0.56 0.512 0.471 0.435 0.404 0.377 14.3% 1.5x
|
44 |
+
1.25 0.498 0.45 0.409 0.376 0.347 0.322 25% 1.5x
|
45 |
+
1.30 0.509 0.46 0.419 0.385 0.356 0.33 25% 1.5x
|
46 |
+
1.35 0.519 0.47 0.429 0.395 0.365 0.339 25% 1.5x
|
47 |
+
1.40 0.529 0.48 0.439 0.404 0.374 0.347 25% 1.5x
|
48 |
+
1.45 0.539 0.49 0.448 0.413 0.382 0.355 25% 1.5x
|
49 |
+
1.50 0.547 0.498 0.456 0.421 0.39 0.363 25% 1.5x
|
50 |
+
1.25 0.467 0.418 0.378 0.345 0.316 0.293 50% 1.5x
|
51 |
+
1.30 0.478 0.428 0.387 0.354 0.325 0.3 50% 1.5x
|
52 |
+
1.35 0.488 0.438 0.397 0.363 0.334 0.309 50% 1.5x
|
53 |
+
1.40 0.498 0.447 0.406 0.372 0.342 0.317 50% 1.5x
|
54 |
+
1.45 0.507 0.457 0.415 0.38 0.35 0.324 50% 1.5x
|
55 |
+
1.50 0.516 0.465 0.423 0.388 0.357 0.331 50% 1.5x
|
56 |
+
1.25 0.411 0.362 0.324 0.292 0.266 0.245 100% 1.5x
|
57 |
+
1.30 0.421 0.371 0.332 0.3 0.274 0.252 100% 1.5x
|
58 |
+
1.35 0.431 0.381 0.341 0.309 0.281 0.259 100% 1.5x
|
59 |
+
1.40 0.44 0.39 0.35 0.317 0.289 0.266 100% 1.5x
|
60 |
+
1.45 0.449 0.399 0.358 0.324 0.296 0.272 100% 1.5x
|
61 |
+
1.50 0.458 0.407 0.366 0.331 0.303 0.279 100% 1.5x
|
62 |
+
1.25 0.545 0.496 0.454 0.418 0.386 0.358 0.1% 2x
|
63 |
+
1.30 0.555 0.507 0.464 0.428 0.396 0.367 0.1% 2x
|
64 |
+
1.35 0.566 0.518 0.475 0.438 0.406 0.377 0.1% 2x
|
65 |
+
1.40 0.577 0.528 0.485 0.448 0.415 0.386 0.1% 2x
|
66 |
+
1.45 0.587 0.538 0.495 0.458 0.424 0.395 0.1% 2x
|
67 |
+
1.50 0.596 0.547 0.504 0.466 0.433 0.403 0.1% 2x
|
68 |
+
1.25 0.523 0.473 0.431 0.395 0.364 0.337 14.3% 2x
|
69 |
+
1.30 0.534 0.484 0.442 0.405 0.373 0.346 14.3% 2x
|
70 |
+
1.35 0.545 0.495 0.452 0.415 0.383 0.355 14.3% 2x
|
71 |
+
1.40 0.555 0.505 0.462 0.425 0.392 0.364 14.3% 2x
|
72 |
+
1.45 0.565 0.515 0.472 0.434 0.401 0.372 14.3% 2x
|
73 |
+
1.50 0.574 0.524 0.481 0.443 0.41 0.38 14.3% 2x
|
74 |
+
1.25 0.51 0.459 0.417 0.381 0.35 0.323 25% 2x
|
75 |
+
1.30 0.52 0.47 0.427 0.391 0.359 0.332 25% 2x
|
76 |
+
1.35 0.531 0.481 0.437 0.401 0.369 0.341 25% 2x
|
77 |
+
1.40 0.542 0.491 0.447 0.41 0.378 0.35 25% 2x
|
78 |
+
1.45 0.552 0.5 0.457 0.419 0.386 0.358 25% 2x
|
79 |
+
1.50 0.561 0.51 0.466 0.428 0.395 0.366 25% 2x
|
80 |
+
1.25 0.477 0.425 0.384 0.348 0.319 0.293 50% 2x
|
81 |
+
1.30 0.487 0.436 0.393 0.358 0.327 0.301 50% 2x
|
82 |
+
1.35 0.498 0.446 0.403 0.367 0.336 0.31 50% 2x
|
83 |
+
1.40 0.509 0.456 0.413 0.376 0.345 0.318 50% 2x
|
84 |
+
1.45 0.518 0.466 0.422 0.385 0.353 0.325 50% 2x
|
85 |
+
1.50 0.527 0.475 0.431 0.393 0.361 0.333 50% 2x
|
86 |
+
1.25 0.418 0.368 0.328 0.295 0.267 0.244 100% 2x
|
87 |
+
1.30 0.429 0.377 0.336 0.303 0.275 0.251 100% 2x
|
88 |
+
1.35 0.439 0.387 0.346 0.311 0.283 0.259 100% 2x
|
89 |
+
1.40 0.449 0.397 0.354 0.319 0.29 0.266 100% 2x
|
90 |
+
1.45 0.458 0.405 0.363 0.327 0.298 0.273 100% 2x
|
91 |
+
1.50 0.467 0.414 0.371 0.335 0.304 0.279 100% 2x
|
PyBDC/dose_table/Sechopoulos_dgn.txt
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10 5.0 0.537 0.517 0.502 0.469 0.438 0.41
|
2 |
+
10 7.5 0.566 0.544 0.527 0.49 0.457 0.427
|
3 |
+
10 10.0 0.582 0.559 0.541 0.503 0.468 0.436
|
4 |
+
12 6.0 0.494 0.474 0.458 0.424 0.395 0.367
|
5 |
+
12 9.0 0.521 0.499 0.482 0.445 0.412 0.382
|
6 |
+
12 12.0 0.536 0.512 0.493 0.455 0.42 0.389
|
7 |
+
14 7.0 0.458 0.437 0.421 0.388 0.358 0.331
|
8 |
+
14 10.5 0.482 0.459 0.442 0.406 0.374 0.345
|
9 |
+
14 14.0 0.494 0.47 0.452 0.414 0.381 0.35
|
10 |
+
16 8.0 0.425 0.404 0.389 0.357 0.328 0.302
|
11 |
+
16 12.0 0.448 0.425 0.408 0.373 0.341 0.314
|
12 |
+
16 16.0 0.458 0.434 0.416 0.379 0.346 0.318
|
13 |
+
18 9.0 0.397 0.376 0.361 0.33 0.302 0.278
|
14 |
+
18 13.5 0.417 0.395 0.378 0.343 0.313 0.287
|
15 |
+
18 18.0 0.425 0.402 0.384 0.348 0.317 0.29
|
PyBDC/incident_spectrum/49kVp_1.5_Al.txt
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10 0.000005
|
2 |
+
11 0.000052
|
3 |
+
12 0.000270
|
4 |
+
13 0.000919
|
5 |
+
14 0.002455
|
6 |
+
15 0.005140
|
7 |
+
16 0.009001
|
8 |
+
17 0.013873
|
9 |
+
18 0.019268
|
10 |
+
19 0.024749
|
11 |
+
20 0.029985
|
12 |
+
21 0.034657
|
13 |
+
22 0.038581
|
14 |
+
23 0.041978
|
15 |
+
24 0.044421
|
16 |
+
25 0.046029
|
17 |
+
26 0.046957
|
18 |
+
27 0.047134
|
19 |
+
28 0.047439
|
20 |
+
29 0.046707
|
21 |
+
30 0.044716
|
22 |
+
31 0.043817
|
23 |
+
32 0.043078
|
24 |
+
33 0.041237
|
25 |
+
34 0.039047
|
26 |
+
35 0.036766
|
27 |
+
36 0.034587
|
28 |
+
37 0.032140
|
29 |
+
38 0.029969
|
30 |
+
39 0.027359
|
31 |
+
40 0.024556
|
32 |
+
41 0.022268
|
33 |
+
42 0.019361
|
34 |
+
43 0.016677
|
35 |
+
44 0.014424
|
36 |
+
45 0.011703
|
37 |
+
46 0.008915
|
38 |
+
47 0.006223
|
39 |
+
48 0.003539
|
40 |
+
49 0.000000
|
PyBDC/incident_spectrum/55kVp1and5mmAl.txt
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
0.5 0.00000E+00
|
2 |
+
1.0 0.00000E+00
|
3 |
+
1.5 0.00000E+00
|
4 |
+
2.0 0.00000E+00
|
5 |
+
2.5 0.00000E+00
|
6 |
+
3.0 0.00000E+00
|
7 |
+
3.5 0.00000E+00
|
8 |
+
4.0 0.00000E+00
|
9 |
+
4.5 0.00000E+00
|
10 |
+
5.0 9.63242E-75
|
11 |
+
5.5 3.22230E-56
|
12 |
+
6.0 1.30434E-42
|
13 |
+
6.5 5.38684E-33
|
14 |
+
7.0 9.92189E-26
|
15 |
+
7.5 3.42140E-20
|
16 |
+
8.0 6.54579E-16
|
17 |
+
8.5 1.54663E-11
|
18 |
+
9.0 6.91632E-10
|
19 |
+
9.5 5.26105E-07
|
20 |
+
10.0 2.55618E-05
|
21 |
+
10.5 7.40239E-05
|
22 |
+
11.0 1.18932E-03
|
23 |
+
11.5 3.03248E-02
|
24 |
+
12.0 6.34224E-02
|
25 |
+
12.5 2.89203E-01
|
26 |
+
13.0 1.22809E+00
|
27 |
+
13.5 4.28942E+00
|
28 |
+
14.0 1.18624E+01
|
29 |
+
14.5 2.94770E+01
|
30 |
+
15.0 6.49330E+01
|
31 |
+
15.5 1.29553E+02
|
32 |
+
16.0 2.38366E+02
|
33 |
+
16.5 4.01789E+02
|
34 |
+
17.0 6.45077E+02
|
35 |
+
17.5 9.66325E+02
|
36 |
+
18.0 1.38945E+03
|
37 |
+
18.5 1.91821E+03
|
38 |
+
19.0 2.54336E+03
|
39 |
+
19.5 3.27831E+03
|
40 |
+
20.0 4.09872E+03
|
41 |
+
20.5 4.97673E+03
|
42 |
+
21.0 5.97946E+03
|
43 |
+
21.5 6.97690E+03
|
44 |
+
22.0 8.05762E+03
|
45 |
+
22.5 9.12192E+03
|
46 |
+
23.0 1.02271E+04
|
47 |
+
23.5 1.12456E+04
|
48 |
+
24.0 1.23600E+04
|
49 |
+
24.5 1.33254E+04
|
50 |
+
25.0 1.42262E+04
|
51 |
+
25.5 1.51835E+04
|
52 |
+
26.0 1.60487E+04
|
53 |
+
26.5 1.67997E+04
|
54 |
+
27.0 1.75761E+04
|
55 |
+
27.5 1.82184E+04
|
56 |
+
28.0 1.88808E+04
|
57 |
+
28.5 1.93798E+04
|
58 |
+
29.0 1.98888E+04
|
59 |
+
29.5 2.02157E+04
|
60 |
+
30.0 2.05444E+04
|
61 |
+
30.5 2.08746E+04
|
62 |
+
31.0 2.10066E+04
|
63 |
+
31.5 2.12165E+04
|
64 |
+
32.0 2.12967E+04
|
65 |
+
32.5 2.13570E+04
|
66 |
+
33.0 2.13518E+04
|
67 |
+
33.5 2.12957E+04
|
68 |
+
34.0 2.11958E+04
|
69 |
+
34.5 2.10743E+04
|
70 |
+
35.0 2.08796E+04
|
71 |
+
35.5 2.06780E+04
|
72 |
+
36.0 2.04332E+04
|
73 |
+
36.5 2.01390E+04
|
74 |
+
37.0 1.98382E+04
|
75 |
+
37.5 1.94961E+04
|
76 |
+
38.0 1.91477E+04
|
77 |
+
38.5 1.87594E+04
|
78 |
+
39.0 1.83457E+04
|
79 |
+
39.5 1.79263E+04
|
80 |
+
40.0 1.74824E+04
|
81 |
+
40.5 1.70148E+04
|
82 |
+
41.0 1.65306E+04
|
83 |
+
41.5 1.60247E+04
|
84 |
+
42.0 1.55146E+04
|
85 |
+
42.5 1.50000E+04
|
86 |
+
43.0 1.44553E+04
|
87 |
+
43.5 1.39219E+04
|
88 |
+
44.0 1.33557E+04
|
89 |
+
44.5 1.27960E+04
|
90 |
+
45.0 1.22155E+04
|
91 |
+
45.5 1.16409E+04
|
92 |
+
46.0 1.10515E+04
|
93 |
+
46.5 1.04489E+04
|
94 |
+
47.0 9.85904E+03
|
95 |
+
47.5 9.25338E+03
|
96 |
+
48.0 8.64038E+03
|
97 |
+
48.5 8.03533E+03
|
98 |
+
49.0 7.42064E+03
|
99 |
+
49.5 6.79816E+03
|
100 |
+
50.0 6.18239E+03
|
101 |
+
50.5 5.56100E+03
|
102 |
+
51.0 4.94017E+03
|
103 |
+
51.5 4.31978E+03
|
104 |
+
52.0 3.69670E+03
|
105 |
+
52.5 3.07839E+03
|
106 |
+
53.0 2.45851E+03
|
107 |
+
53.5 1.84066E+03
|
108 |
+
54.0 1.22494E+03
|
109 |
+
54.5 6.10877E+02
|
110 |
+
55.0 5.09474E+01
|
PyBDC/incident_spectrum/60kV_0.2_Cu.txt
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10 2.17528E-22
|
2 |
+
11 8.14884E-18
|
3 |
+
12 1.18017E-14
|
4 |
+
13 4.01619E-12
|
5 |
+
14 3.10445E-10
|
6 |
+
15 1.10769E-8
|
7 |
+
16 1.7833E-7
|
8 |
+
17 1.78574E-6
|
9 |
+
18 1.08941E-5
|
10 |
+
19 4.29721E-5
|
11 |
+
20 0.00013648
|
12 |
+
21 0.000352846
|
13 |
+
22 0.000795833
|
14 |
+
23 0.00154393
|
15 |
+
24 0.00274503
|
16 |
+
25 0.0044029
|
17 |
+
26 0.00659502
|
18 |
+
27 0.00925285
|
19 |
+
28 0.0124491
|
20 |
+
29 0.0156588
|
21 |
+
30 0.0191672
|
22 |
+
31 0.0226594
|
23 |
+
32 0.026303
|
24 |
+
33 0.0295566
|
25 |
+
34 0.0326895
|
26 |
+
35 0.0355168
|
27 |
+
36 0.0380014
|
28 |
+
37 0.0400384
|
29 |
+
38 0.0417079
|
30 |
+
39 0.0430091
|
31 |
+
40 0.0438818
|
32 |
+
41 0.0446358
|
33 |
+
42 0.0448787
|
34 |
+
43 0.0438065
|
35 |
+
44 0.0424666
|
36 |
+
45 0.0419685
|
37 |
+
46 0.0411065
|
38 |
+
47 0.0389167
|
39 |
+
48 0.0364259
|
40 |
+
49 0.0349405
|
41 |
+
50 0.0331506
|
42 |
+
51 0.031304
|
43 |
+
52 0.0285168
|
44 |
+
53 0.0258341
|
45 |
+
54 0.0229194
|
46 |
+
55 0.0197738
|
47 |
+
56 0.0166468
|
48 |
+
57 0.0122853
|
49 |
+
58 0.00856324
|
50 |
+
59 0.00534053
|
51 |
+
60 0
|
PyBDC/incident_spectrum/spectrum_45kVp_1mm.txt
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10.0 6.20275E+02
|
2 |
+
10.5 2.26229E+02
|
3 |
+
11.0 5.25667E+02
|
4 |
+
11.5 2.39324E+03
|
5 |
+
12.0 1.45979E+03
|
6 |
+
12.5 2.17293E+03
|
7 |
+
13.0 3.36611E+03
|
8 |
+
13.5 4.89394E+03
|
9 |
+
14.0 6.61405E+03
|
10 |
+
14.5 8.62495E+03
|
11 |
+
15.0 1.08154E+04
|
12 |
+
15.5 1.31267E+04
|
13 |
+
16.0 1.55160E+04
|
14 |
+
16.5 1.78455E+04
|
15 |
+
17.0 2.01852E+04
|
16 |
+
17.5 2.23424E+04
|
17 |
+
18.0 2.44012E+04
|
18 |
+
18.5 2.63015E+04
|
19 |
+
19.0 2.79851E+04
|
20 |
+
19.5 2.95090E+04
|
21 |
+
20.0 3.08127E+04
|
22 |
+
20.5 3.18808E+04
|
23 |
+
21.0 3.28623E+04
|
24 |
+
21.5 3.35728E+04
|
25 |
+
22.0 3.41728E+04
|
26 |
+
22.5 3.45705E+04
|
27 |
+
23.0 3.48584E+04
|
28 |
+
23.5 3.49344E+04
|
29 |
+
24.0 3.49933E+04
|
30 |
+
24.5 3.48417E+04
|
31 |
+
25.0 3.45781E+04
|
32 |
+
25.5 3.42969E+04
|
33 |
+
26.0 3.39089E+04
|
34 |
+
26.5 3.34169E+04
|
35 |
+
27.0 3.29077E+04
|
36 |
+
27.5 3.23026E+04
|
37 |
+
28.0 3.16857E+04
|
38 |
+
28.5 3.09750E+04
|
39 |
+
29.0 3.02595E+04
|
40 |
+
29.5 2.94586E+04
|
41 |
+
30.0 2.86493E+04
|
42 |
+
30.5 2.78391E+04
|
43 |
+
31.0 2.69503E+04
|
44 |
+
31.5 2.60902E+04
|
45 |
+
32.0 2.51812E+04
|
46 |
+
32.5 2.42670E+04
|
47 |
+
33.0 2.33337E+04
|
48 |
+
33.5 2.23855E+04
|
49 |
+
34.0 2.14273E+04
|
50 |
+
34.5 2.04647E+04
|
51 |
+
35.0 1.94856E+04
|
52 |
+
35.5 1.85087E+04
|
53 |
+
36.0 1.75235E+04
|
54 |
+
36.5 1.65319E+04
|
55 |
+
37.0 1.55422E+04
|
56 |
+
37.5 1.45481E+04
|
57 |
+
38.0 1.35556E+04
|
58 |
+
38.5 1.25620E+04
|
59 |
+
39.0 1.15682E+04
|
60 |
+
39.5 1.05783E+04
|
61 |
+
40.0 9.59146E+03
|
62 |
+
40.5 8.60563E+03
|
63 |
+
41.0 7.62402E+03
|
64 |
+
41.5 6.64697E+03
|
65 |
+
42.0 5.67573E+03
|
66 |
+
42.5 4.71213E+03
|
67 |
+
43.0 3.75295E+03
|
68 |
+
43.5 2.80302E+03
|
69 |
+
44.0 1.85971E+03
|
70 |
+
44.5 9.25674E+02
|
71 |
+
45.0 7.69817E+01
|
PyBDC/incident_spectrum/spectrum_55kVp2mmAl.txt
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
10.0 1.03261E+00
|
2 |
+
10.5 7.25697E-01
|
3 |
+
11.0 3.60250E+00
|
4 |
+
11.5 3.47511E+01
|
5 |
+
12.0 3.10489E+01
|
6 |
+
12.5 7.12270E+01
|
7 |
+
13.0 1.64755E+02
|
8 |
+
13.5 3.39900E+02
|
9 |
+
14.0 6.12087E+02
|
10 |
+
14.5 1.03443E+03
|
11 |
+
15.0 1.62840E+03
|
12 |
+
15.5 2.41775E+03
|
13 |
+
16.0 3.42141E+03
|
14 |
+
16.5 4.59823E+03
|
15 |
+
17.0 6.00213E+03
|
16 |
+
17.5 7.52135E+03
|
17 |
+
18.0 9.19726E+03
|
18 |
+
18.5 1.09780E+04
|
19 |
+
19.0 1.27941E+04
|
20 |
+
19.5 1.46615E+04
|
21 |
+
20.0 1.65011E+04
|
22 |
+
20.5 1.82538E+04
|
23 |
+
21.0 2.00621E+04
|
24 |
+
21.5 2.16749E+04
|
25 |
+
22.0 2.32724E+04
|
26 |
+
22.5 2.46970E+04
|
27 |
+
23.0 2.60571E+04
|
28 |
+
23.5 2.71826E+04
|
29 |
+
24.0 2.83441E+04
|
30 |
+
24.5 2.92264E+04
|
31 |
+
25.0 2.99637E+04
|
32 |
+
25.5 3.07107E+04
|
33 |
+
26.0 3.12987E+04
|
34 |
+
26.5 3.17189E+04
|
35 |
+
27.0 3.21317E+04
|
36 |
+
27.5 3.23749E+04
|
37 |
+
28.0 3.26141E+04
|
38 |
+
28.5 3.26725E+04
|
39 |
+
29.0 3.27255E+04
|
40 |
+
29.5 3.25966E+04
|
41 |
+
30.0 3.24626E+04
|
42 |
+
30.5 3.23231E+04
|
43 |
+
31.0 3.20048E+04
|
44 |
+
31.5 3.17528E+04
|
45 |
+
32.0 3.13888E+04
|
46 |
+
32.5 3.10090E+04
|
47 |
+
33.0 3.05767E+04
|
48 |
+
33.5 3.01054E+04
|
49 |
+
34.0 2.96024E+04
|
50 |
+
34.5 2.90859E+04
|
51 |
+
35.0 2.85162E+04
|
52 |
+
35.5 2.79459E+04
|
53 |
+
36.0 2.73471E+04
|
54 |
+
36.5 2.67159E+04
|
55 |
+
37.0 2.60849E+04
|
56 |
+
37.5 2.54284E+04
|
57 |
+
38.0 2.47724E+04
|
58 |
+
38.5 2.40924E+04
|
59 |
+
39.0 2.33991E+04
|
60 |
+
39.5 2.27069E+04
|
61 |
+
40.0 2.20023E+04
|
62 |
+
40.5 2.12857E+04
|
63 |
+
41.0 2.05624E+04
|
64 |
+
41.5 1.98287E+04
|
65 |
+
42.0 1.90970E+04
|
66 |
+
42.5 1.83669E+04
|
67 |
+
43.0 1.76205E+04
|
68 |
+
43.5 1.68865E+04
|
69 |
+
44.0 1.61343E+04
|
70 |
+
44.5 1.53910E+04
|
71 |
+
45.0 1.46378E+04
|
72 |
+
45.5 1.38928E+04
|
73 |
+
46.0 1.31420E+04
|
74 |
+
46.5 1.23864E+04
|
75 |
+
47.0 1.16434E+04
|
76 |
+
47.5 1.08937E+04
|
77 |
+
48.0 1.01431E+04
|
78 |
+
48.5 9.40177E+03
|
79 |
+
49.0 8.65784E+03
|
80 |
+
49.5 7.91256E+03
|
81 |
+
50.0 7.17559E+03
|
82 |
+
50.5 6.43871E+03
|
83 |
+
51.0 5.70601E+03
|
84 |
+
51.5 4.97741E+03
|
85 |
+
52.0 4.25085E+03
|
86 |
+
52.5 3.53126E+03
|
87 |
+
53.0 2.81449E+03
|
88 |
+
53.5 2.10291E+03
|
89 |
+
54.0 1.39664E+03
|
90 |
+
54.5 6.95374E+02
|
91 |
+
55.0 5.78772E+01
|
PyBDC/method_specific_inputs.toml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# method_specific_inputs.toml
|
2 |
+
|
3 |
+
[method_specific_inputs]
|
4 |
+
Sarno_49_specific_output = "This method assumes a cylindrical breast shape of homogeneous mixture where air kerma is measured from the radiation source. The method further provides different Al filtrations."
|
5 |
+
|
6 |
+
Sarno_specific_outputs = """
|
7 |
+
Any spectrum can be used as long as radiation source to isocenter distance is 65 cm.
|
8 |
+
|
9 |
+
It assumes heterogeneous composition."""
|
10 |
+
|
11 |
+
Hernandez_specific_output = """
|
12 |
+
Any spectrum can be used as long as radiation source to isocenter distance is 65 cm.
|
13 |
+
|
14 |
+
It assumes heterogeneous composition.
|
15 |
+
|
16 |
+
Hernandez VGF median specifications:
|
17 |
+
V1:
|
18 |
+
- volume of 276 cm^3
|
19 |
+
- center of mass diameter of 87 mm
|
20 |
+
- chest wall diameter of 103.4 mm
|
21 |
+
V3:
|
22 |
+
- volume of 616 cm^3
|
23 |
+
- center of mass diameter of 106.6 mm
|
24 |
+
- chest wall diameter of 125.2
|
25 |
+
V5:
|
26 |
+
- volume of 1174 cm^3
|
27 |
+
- center of mass diameter of 124.4 mm
|
28 |
+
- chest wall diameter of 150.4 mm"""
|
29 |
+
|
30 |
+
Sechopoulos_specific_output = "It assumes a semi-ellipsoidal breast shape of homogeneous mixture where air kerma is measured 65 cm from radiation source."
|
PyBDC/requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
customtkinter==5.2.2
|
2 |
+
matplotlib==3.8.0
|
3 |
+
numpy==1.26.0
|
4 |
+
pandas==1.3.4
|
5 |
+
tomli
|