OpenREM 1.0.0b2__py3-none-any.whl → 1.0.0b3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openrem/locale/de/LC_MESSAGES/django.po +1060 -1059
- openrem/locale/django.pot +973 -972
- openrem/locale/es_MX/LC_MESSAGES/django.po +1049 -1048
- openrem/locale/it/LC_MESSAGES/django.po +1044 -1043
- openrem/locale/lt/LC_MESSAGES/django.po +989 -988
- openrem/locale/nb_NO/LC_MESSAGES/django.po +985 -984
- openrem/locale/pt_BR/LC_MESSAGES/django.po +1003 -1002
- openrem/manage.py +10 -10
- openrem/openremproject/__init__.py +1 -1
- openrem/openremproject/local_settings.py.linux +128 -128
- openrem/openremproject/local_settings.py.windows +144 -144
- openrem/openremproject/local_settings.py.windows-sqlite3 +129 -129
- openrem/openremproject/settings.py +278 -278
- openrem/openremproject/urls.py +32 -32
- openrem/openremproject/wsgi.py.example +28 -28
- openrem/remapp/__init__.py +2 -2
- openrem/remapp/admin.py +31 -31
- openrem/remapp/exports/ct_export.py +780 -753
- openrem/remapp/exports/dx_export.py +817 -805
- openrem/remapp/exports/export_common.py +931 -951
- openrem/remapp/exports/export_common_pandas.py +2422 -0
- openrem/remapp/exports/exportviews.py +815 -860
- openrem/remapp/exports/mg_csv_nhsbsp.py +292 -292
- openrem/remapp/exports/mg_export.py +673 -510
- openrem/remapp/exports/nm_export.py +796 -575
- openrem/remapp/exports/rf_export.py +1418 -1431
- openrem/remapp/extractors/ct_philips.py +424 -414
- openrem/remapp/extractors/ct_toshiba.py +2116 -2108
- openrem/remapp/extractors/dx.py +1033 -952
- openrem/remapp/extractors/extract_common.py +817 -817
- openrem/remapp/extractors/import_views.py +426 -426
- openrem/remapp/extractors/mam.py +685 -672
- openrem/remapp/extractors/nm_image.py +439 -431
- openrem/remapp/extractors/ptsizecsv2db.py +368 -368
- openrem/remapp/extractors/rdsr.py +667 -654
- openrem/remapp/extractors/rdsr_methods.py +1771 -1768
- openrem/remapp/extractors/rrdsr_methods.py +630 -622
- openrem/remapp/fixtures/openskin_safelist.json +11 -11
- openrem/remapp/forms.py +2286 -2277
- openrem/remapp/interface/chart_functions.py +2412 -2393
- openrem/remapp/interface/mod_filters.py +1241 -1243
- openrem/remapp/migrations/0001_initial.py.1-0-upgrade +1043 -1043
- openrem/remapp/models.py +3418 -3407
- openrem/remapp/netdicom/dicomviews.py +681 -683
- openrem/remapp/netdicom/qrscu.py +2646 -2646
- openrem/remapp/netdicom/tools.py +134 -134
- openrem/remapp/static/css/bootstrap-theme.css +587 -587
- openrem/remapp/static/css/bootstrap-theme.min.css +4 -4
- openrem/remapp/static/css/bootstrap.css +6800 -6800
- openrem/remapp/static/css/bootstrap.min.css +4 -4
- openrem/remapp/static/css/datepicker3.css +790 -790
- openrem/remapp/static/css/jquery.qtip.min.css +2 -2
- openrem/remapp/static/css/openrem-extra.css +442 -442
- openrem/remapp/static/css/openrem.css +96 -96
- openrem/remapp/static/css/registration.css +34 -34
- openrem/remapp/static/fonts/glyphicons-halflings-regular.svg +287 -287
- openrem/remapp/static/js/bootstrap-datepicker.js +1671 -1671
- openrem/remapp/static/js/bootstrap.js +2363 -2363
- openrem/remapp/static/js/bootstrap.min.js +6 -6
- openrem/remapp/static/js/charts/chartCommonFunctions.js +75 -75
- openrem/remapp/static/js/charts/chartFullScreen.js +41 -41
- openrem/remapp/static/js/charts/ctChartAjax.js +331 -331
- openrem/remapp/static/js/charts/dxChartAjax.js +290 -290
- openrem/remapp/static/js/charts/mgChartAjax.js +144 -144
- openrem/remapp/static/js/charts/nmChartAjax.js +64 -64
- openrem/remapp/static/js/charts/plotly-2.35.2.min.js +8 -0
- openrem/remapp/static/js/charts/rfChartAjax.js +128 -128
- openrem/remapp/static/js/chroma.min.js +32 -32
- openrem/remapp/static/js/datepicker.js +5 -5
- openrem/remapp/static/js/dicom.js +115 -115
- openrem/remapp/static/js/django_reverse/reverse.js +13 -13
- openrem/remapp/static/js/formatDate.js +7 -7
- openrem/remapp/static/js/html5shiv.min.js +8 -8
- openrem/remapp/static/js/jquery-1.11.0.min.js +4 -4
- openrem/remapp/static/js/npm.js +12 -12
- openrem/remapp/static/js/respond.min.js +4 -4
- openrem/remapp/static/js/skin-dose-maps/jquery.qtip.min.js +4 -4
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMap3dHUDObject.js +112 -112
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMap3dObject.js +367 -367
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMap3dPersonObject.js +158 -158
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMapColourScaleObject.js +153 -153
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMapObject.js +367 -367
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMapping.js +584 -584
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMapping3d.js +255 -255
- openrem/remapp/static/js/skin-dose-maps/rfSkinDoseMappingAjax.js +267 -212
- openrem/remapp/static/js/skin-dose-maps/three.min.js +835 -835
- openrem/remapp/static/js/sorttable.js +495 -495
- openrem/remapp/templates/base.html +253 -253
- openrem/remapp/templates/registration/changepassword.html +25 -25
- openrem/remapp/templates/registration/changepassworddone.html +12 -12
- openrem/remapp/templates/registration/login.html +42 -42
- openrem/remapp/templates/remapp/backgroundtaskmaximumrows_form.html +29 -29
- openrem/remapp/templates/remapp/base.html +1 -1
- openrem/remapp/templates/remapp/ctdetail.html +235 -235
- openrem/remapp/templates/remapp/ctfiltered.html +310 -310
- openrem/remapp/templates/remapp/dicomdeletesettings_form.html +31 -31
- openrem/remapp/templates/remapp/dicomqr.html +147 -147
- openrem/remapp/templates/remapp/dicomquerydetails.html +83 -83
- openrem/remapp/templates/remapp/dicomqueryimages.html +49 -49
- openrem/remapp/templates/remapp/dicomqueryseries.html +109 -109
- openrem/remapp/templates/remapp/dicomquerysummary.html +48 -48
- openrem/remapp/templates/remapp/dicomremoteqr_confirm_delete.html +60 -60
- openrem/remapp/templates/remapp/dicomremoteqr_form.html +32 -32
- openrem/remapp/templates/remapp/dicomstorescp_confirm_delete.html +53 -53
- openrem/remapp/templates/remapp/dicomstorescp_form.html +48 -48
- openrem/remapp/templates/remapp/dicomsummary.html +257 -257
- openrem/remapp/templates/remapp/displaychartoptions.html +184 -184
- openrem/remapp/templates/remapp/displayhomepageoptions.html +57 -57
- openrem/remapp/templates/remapp/displayname-count.html +6 -6
- openrem/remapp/templates/remapp/displayname-last-date.html +3 -3
- openrem/remapp/templates/remapp/displayname-modality.html +86 -105
- openrem/remapp/templates/remapp/displayname-skinmap.html +18 -18
- openrem/remapp/templates/remapp/displaynameupdate.html +100 -100
- openrem/remapp/templates/remapp/displaynameview.html +222 -219
- openrem/remapp/templates/remapp/dxdetail.html +176 -176
- openrem/remapp/templates/remapp/dxfiltered.html +324 -324
- openrem/remapp/templates/remapp/exports-active.html +25 -25
- openrem/remapp/templates/remapp/exports-complete.html +35 -35
- openrem/remapp/templates/remapp/exports-error.html +26 -26
- openrem/remapp/templates/remapp/exports-queue.html +18 -18
- openrem/remapp/templates/remapp/exports.html +191 -191
- openrem/remapp/templates/remapp/failed_summary_list.html +27 -27
- openrem/remapp/templates/remapp/filteredbase.html +162 -162
- openrem/remapp/templates/remapp/highdosemetricalertsettings_form.html +76 -76
- openrem/remapp/templates/remapp/home-list-modalities.html +94 -94
- openrem/remapp/templates/remapp/home.html +202 -202
- openrem/remapp/templates/remapp/list_filters.html +24 -24
- openrem/remapp/templates/remapp/mgdetail.html +160 -138
- openrem/remapp/templates/remapp/mgfiltered.html +311 -311
- openrem/remapp/templates/remapp/nmdetail.html +300 -300
- openrem/remapp/templates/remapp/nmfiltered.html +255 -255
- openrem/remapp/templates/remapp/notpatient.html +190 -190
- openrem/remapp/templates/remapp/notpatientindicators_form_base.html +81 -81
- openrem/remapp/templates/remapp/notpatientindicatorsid_confirm_delete.html +54 -54
- openrem/remapp/templates/remapp/notpatientindicatorsid_form.html +23 -23
- openrem/remapp/templates/remapp/notpatientindicatorsname_confirm_delete.html +54 -54
- openrem/remapp/templates/remapp/notpatientindicatorsname_form.html +23 -23
- openrem/remapp/templates/remapp/notpatientindicatorsname_form_base.html +85 -85
- openrem/remapp/templates/remapp/openskinsafelist_add.html +130 -130
- openrem/remapp/templates/remapp/openskinsafelist_confirm_delete.html +100 -100
- openrem/remapp/templates/remapp/openskinsafelist_form.html +207 -207
- openrem/remapp/templates/remapp/patientidsettings_form.html +83 -83
- openrem/remapp/templates/remapp/populate_summary_progress.html +83 -83
- openrem/remapp/templates/remapp/populate_summary_progress_error.html +36 -36
- openrem/remapp/templates/remapp/review_failed_imports.html +157 -157
- openrem/remapp/templates/remapp/review_failed_study.html +41 -41
- openrem/remapp/templates/remapp/review_studies_delete_button.html +20 -20
- openrem/remapp/templates/remapp/review_study.html +19 -19
- openrem/remapp/templates/remapp/review_summary_list.html +245 -245
- openrem/remapp/templates/remapp/rf_dose_alert_email_template.html +14 -1
- openrem/remapp/templates/remapp/rfalertnotificationsview.html +59 -59
- openrem/remapp/templates/remapp/rfdetail.html +547 -543
- openrem/remapp/templates/remapp/rfdetailbase.html +18 -18
- openrem/remapp/templates/remapp/rffiltered.html +404 -404
- openrem/remapp/templates/remapp/sizeimports.html +119 -119
- openrem/remapp/templates/remapp/sizeprocess.html +96 -96
- openrem/remapp/templates/remapp/sizeupload.html +110 -110
- openrem/remapp/templates/remapp/skindosemapcalcsettings_form.html +28 -28
- openrem/remapp/templates/remapp/standardname-modality.html +69 -69
- openrem/remapp/templates/remapp/standardnames_confirm_delete.html +71 -71
- openrem/remapp/templates/remapp/standardnames_form.html +87 -87
- openrem/remapp/templates/remapp/standardnamesettings_form.html +41 -41
- openrem/remapp/templates/remapp/standardnamesrefreshall.html +92 -92
- openrem/remapp/templates/remapp/standardnameview.html +103 -103
- openrem/remapp/templates/remapp/study_confirm_delete.html +147 -147
- openrem/remapp/templates/remapp/task_admin.html +265 -265
- openrem/remapp/templates/remapp/tasks.html +76 -76
- openrem/remapp/templatetags/formfilters.py +13 -13
- openrem/remapp/templatetags/proper_paginate.py +38 -38
- openrem/remapp/templatetags/remappduration.py +36 -36
- openrem/remapp/templatetags/sigdig.py +38 -38
- openrem/remapp/templatetags/sort_class_property_value.py +15 -15
- openrem/remapp/templatetags/update_variable.py +20 -20
- openrem/remapp/templatetags/url_replace.py +25 -25
- openrem/remapp/tests/test_charts_common.py +202 -202
- openrem/remapp/tests/test_charts_ct.py +7111 -7111
- openrem/remapp/tests/test_charts_dx.py +3513 -3513
- openrem/remapp/tests/test_charts_mg.py +1116 -1115
- openrem/remapp/tests/test_dcmdatetime.py +189 -189
- openrem/remapp/tests/test_dicom_qr.py +2580 -2580
- openrem/remapp/tests/test_display_name.py +274 -274
- openrem/remapp/tests/test_export_ct_xlsx.py +272 -248
- openrem/remapp/tests/test_export_dx_xlsx.py +137 -134
- openrem/remapp/tests/test_export_mammo_csv.py +242 -242
- openrem/remapp/tests/test_export_rf_xlsx.py +246 -246
- openrem/remapp/tests/test_files/DX-Im-DRGEM.dcm +0 -0
- openrem/remapp/tests/test_files/MG-RDSR-GEPristina-2D.dcm +0 -0
- openrem/remapp/tests/test_files/MG-RDSR-GEPristina-DBT.dcm +0 -0
- openrem/remapp/tests/test_files/MG-RDSR-Giotto-DBT.dcm +0 -0
- openrem/remapp/tests/test_files/skin_map_alphenix.py +590 -590
- openrem/remapp/tests/test_files/skin_map_zee.py +354 -354
- openrem/remapp/tests/test_filters_ct.py +321 -321
- openrem/remapp/tests/test_filters_dx.py +92 -92
- openrem/remapp/tests/test_filters_mammo.py +183 -183
- openrem/remapp/tests/test_filters_rf.py +118 -118
- openrem/remapp/tests/test_get_values.py +72 -72
- openrem/remapp/tests/test_hash_id.py +65 -65
- openrem/remapp/tests/test_import_ct_esr_ge.py +3034 -3034
- openrem/remapp/tests/test_import_ct_philips_rdsr.py +42 -42
- openrem/remapp/tests/test_import_ct_rdsr_multiple.py +256 -256
- openrem/remapp/tests/test_import_ct_rdsr_siemens.py +827 -827
- openrem/remapp/tests/test_import_ct_rdsr_spectrumdynamics.py +91 -91
- openrem/remapp/tests/test_import_ct_rdsr_toshiba_dosecheck.py +67 -67
- openrem/remapp/tests/test_import_ct_rdsr_toshiba_multivaluesd.py +33 -33
- openrem/remapp/tests/test_import_ct_rdsr_toshiba_pixelmed.py +118 -118
- openrem/remapp/tests/test_import_ct_sc_philips.py +44 -44
- openrem/remapp/tests/test_import_dual_rdsr.py +110 -110
- openrem/remapp/tests/test_import_dx.py +1267 -1191
- openrem/remapp/tests/test_import_dx_rdsr.py +1250 -1253
- openrem/remapp/tests/test_import_mam.py +438 -438
- openrem/remapp/tests/test_import_mg_im_hol_proj.py +46 -46
- openrem/remapp/tests/test_import_mg_rdsr.py +586 -586
- openrem/remapp/tests/test_import_nm_image.py +420 -420
- openrem/remapp/tests/test_import_nm_siemens_rdsr.py +396 -396
- openrem/remapp/tests/test_import_px.py +161 -161
- openrem/remapp/tests/test_import_rf_rdsr.py +420 -418
- openrem/remapp/tests/test_missing_date.py +42 -42
- openrem/remapp/tests/test_not_patient.py +60 -60
- openrem/remapp/tests/test_openskin.py +272 -272
- openrem/remapp/tests/test_patient_id_settings.py +72 -72
- openrem/remapp/tests/test_pt_size_import.py +232 -232
- openrem/remapp/tests/test_rf_detail.py +113 -113
- openrem/remapp/tests/test_rf_high_dose_alert.py +361 -361
- openrem/remapp/tools/background.py +361 -361
- openrem/remapp/tools/check_standard_name_status.py +47 -0
- openrem/remapp/tools/check_uid.py +70 -70
- openrem/remapp/tools/dcmdatetime.py +248 -248
- openrem/remapp/tools/default_import.py +44 -47
- openrem/remapp/tools/get_values.py +230 -230
- openrem/remapp/tools/hash_id.py +58 -58
- openrem/remapp/tools/make_skin_map.py +448 -406
- openrem/remapp/tools/not_patient_indicators.py +72 -72
- openrem/remapp/tools/openskin/calc_exp_map.py +173 -173
- openrem/remapp/tools/openskin/geomclass.py +475 -475
- openrem/remapp/tools/openskin/geomfunc.py +433 -432
- openrem/remapp/tools/openskin/skinmap.py +417 -417
- openrem/remapp/tools/populate_summary.py +185 -193
- openrem/remapp/tools/save_skin_map_structure.py +73 -73
- openrem/remapp/tools/send_high_dose_alert_emails.py +238 -207
- openrem/remapp/urls.py +456 -448
- openrem/remapp/version.py +11 -11
- openrem/remapp/views.py +1147 -1052
- openrem/remapp/views_admin.py +3876 -3936
- openrem/remapp/views_charts_ct.py +2110 -2058
- openrem/remapp/views_charts_dx.py +1906 -1836
- openrem/remapp/views_charts_mg.py +1349 -1196
- openrem/remapp/views_charts_nm.py +535 -535
- openrem/remapp/views_charts_rf.py +1219 -1241
- openrem/remapp/views_openskin.py +379 -384
- openrem/sample-config/openrem-consumer.service +12 -12
- openrem/sample-config/openrem-gunicorn.service +13 -13
- openrem/sample-config/openrem-server +14 -13
- openrem/sample-config/openrem_orthanc_config_linux.lua +454 -454
- openrem/sample-config/openrem_orthanc_config_windows.lua +455 -455
- openrem/sample-config/queue-init.bat +73 -73
- openrem/scripts/openrem_ctphilips.py +25 -25
- openrem/scripts/openrem_cttoshiba.py +28 -28
- openrem/scripts/openrem_dx.py +22 -22
- openrem/scripts/openrem_mg.py +22 -22
- openrem/scripts/openrem_nm.py +22 -22
- openrem/scripts/openrem_ptsizecsv.py +17 -17
- openrem/scripts/openrem_qr.py +12 -12
- openrem/scripts/openrem_rdsr.py +25 -25
- {OpenREM-1.0.0b2.dist-info → openrem-1.0.0b3.dist-info}/METADATA +39 -29
- openrem-1.0.0b3.dist-info/RECORD +379 -0
- {OpenREM-1.0.0b2.dist-info → openrem-1.0.0b3.dist-info}/WHEEL +1 -1
- {OpenREM-1.0.0b2.dist-info → openrem-1.0.0b3.dist-info/licenses}/COPYING-GPLv3 +674 -674
- {OpenREM-1.0.0b2.dist-info → openrem-1.0.0b3.dist-info/licenses}/LICENSE +22 -22
- OpenREM-1.0.0b2.dist-info/RECORD +0 -373
- openrem/remapp/static/js/charts/plotly-2.17.1.min.js +0 -8
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_ctphilips.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_cttoshiba.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_dx.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_mg.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_nm.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_ptsizecsv.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_qr.py +0 -0
- {OpenREM-1.0.0b2.data → openrem-1.0.0b3.data}/scripts/openrem_rdsr.py +0 -0
- {OpenREM-1.0.0b2.dist-info → openrem-1.0.0b3.dist-info}/top_level.txt +0 -0
|
@@ -1,406 +1,448 @@
|
|
|
1
|
-
# This Python file uses the following encoding: utf-8
|
|
2
|
-
# OpenREM - Radiation Exposure Monitoring tools for the physicist
|
|
3
|
-
# Copyright (C) 2012,2013 The Royal Marsden NHS Foundation Trust
|
|
4
|
-
#
|
|
5
|
-
# This program is free software: you can redistribute it and/or modify
|
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
|
7
|
-
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
# (at your option) any later version.
|
|
9
|
-
#
|
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
# GNU General Public License for more details.
|
|
14
|
-
#
|
|
15
|
-
# Additional permission under section 7 of GPLv3:
|
|
16
|
-
# You shall not make any use of the name of The Royal Marsden NHS
|
|
17
|
-
# Foundation trust in connection with this Program in any press or
|
|
18
|
-
# other public announcement without the prior written consent of
|
|
19
|
-
# The Royal Marsden NHS Foundation Trust.
|
|
20
|
-
#
|
|
21
|
-
# You should have received a copy of the GNU General Public License
|
|
22
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
23
|
-
|
|
24
|
-
"""
|
|
25
|
-
.. module:: make_skin_map.
|
|
26
|
-
:synopsis: Module to calculate skin dose map from study data.
|
|
27
|
-
|
|
28
|
-
.. moduleauthor:: Ed McDonagh, David Platten, Wens Kong
|
|
29
|
-
|
|
30
|
-
"""
|
|
31
|
-
import
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# django
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
from .
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
from
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
.
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
irrad.irradeventxraymechanicaldata_set.get().
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
try:
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
except (ObjectDoesNotExist, TypeError):
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
except
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
try:
|
|
366
|
-
|
|
367
|
-
except
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
1
|
+
# This Python file uses the following encoding: utf-8
|
|
2
|
+
# OpenREM - Radiation Exposure Monitoring tools for the physicist
|
|
3
|
+
# Copyright (C) 2012,2013 The Royal Marsden NHS Foundation Trust
|
|
4
|
+
#
|
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# Additional permission under section 7 of GPLv3:
|
|
16
|
+
# You shall not make any use of the name of The Royal Marsden NHS
|
|
17
|
+
# Foundation trust in connection with this Program in any press or
|
|
18
|
+
# other public announcement without the prior written consent of
|
|
19
|
+
# The Royal Marsden NHS Foundation Trust.
|
|
20
|
+
#
|
|
21
|
+
# You should have received a copy of the GNU General Public License
|
|
22
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
.. module:: make_skin_map.
|
|
26
|
+
:synopsis: Module to calculate skin dose map from study data.
|
|
27
|
+
|
|
28
|
+
.. moduleauthor:: Ed McDonagh, David Platten, Wens Kong
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
import decimal
|
|
32
|
+
import os
|
|
33
|
+
import sys
|
|
34
|
+
import logging
|
|
35
|
+
|
|
36
|
+
import django
|
|
37
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
38
|
+
import numpy as np
|
|
39
|
+
|
|
40
|
+
# Setup django. This is required on windows, because process is created via spawn and
|
|
41
|
+
# django will not be initialized anymore then (On Linux this will only be executed once)
|
|
42
|
+
basepath = os.path.dirname(__file__)
|
|
43
|
+
projectpath = os.path.abspath(os.path.join(basepath, "..", ".."))
|
|
44
|
+
if projectpath not in sys.path:
|
|
45
|
+
sys.path.insert(1, projectpath)
|
|
46
|
+
os.environ["DJANGO_SETTINGS_MODULE"] = "openremproject.settings"
|
|
47
|
+
django.setup()
|
|
48
|
+
|
|
49
|
+
from remapp.models import ( # pylint: disable=wrong-import-position
|
|
50
|
+
GeneralStudyModuleAttr,
|
|
51
|
+
SkinDoseMapResults,
|
|
52
|
+
OpenSkinSafeList,
|
|
53
|
+
)
|
|
54
|
+
from .background import ( # pylint: disable=wrong-import-position
|
|
55
|
+
get_current_task,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
from .save_skin_map_structure import ( # pylint: disable=wrong-import-position
|
|
59
|
+
save_openskin_structure,
|
|
60
|
+
)
|
|
61
|
+
from .openskin.calc_exp_map import CalcExpMap # pylint: disable=wrong-import-position
|
|
62
|
+
from ..version import __skin_map_version__ # pylint: disable=wrong-import-position
|
|
63
|
+
|
|
64
|
+
# Explicitly name logger so that it is still handled when using __main__
|
|
65
|
+
logger = logging.getLogger("remapp.tools.make_skin_map")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def make_skin_map(study_pk=None):
|
|
69
|
+
# pylint: disable=too-many-branches
|
|
70
|
+
# pylint: disable=too-many-statements
|
|
71
|
+
# pylint: disable=too-many-locals
|
|
72
|
+
# noqa: C901
|
|
73
|
+
|
|
74
|
+
background_task = get_current_task()
|
|
75
|
+
|
|
76
|
+
if study_pk:
|
|
77
|
+
study = GeneralStudyModuleAttr.objects.prefetch_related(
|
|
78
|
+
"projectionxrayradiationdose_set__irradeventxraydata_set"
|
|
79
|
+
).get(pk=study_pk)
|
|
80
|
+
# study = GeneralStudyModuleAttr.objects.get(pk=study_pk)
|
|
81
|
+
|
|
82
|
+
display_name = (
|
|
83
|
+
study.generalequipmentmoduleattr_set.get().unique_equipment_name.display_name
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if background_task is not None:
|
|
87
|
+
background_task.info = (
|
|
88
|
+
f"Unit: {display_name} | "
|
|
89
|
+
f"PK: {study_pk} | Study UID: {study.study_instance_uid.replace('.', '. ')}"
|
|
90
|
+
)
|
|
91
|
+
background_task.save()
|
|
92
|
+
|
|
93
|
+
pat_mass_source = "assumed"
|
|
94
|
+
try:
|
|
95
|
+
pat_mass = float(study.patientstudymoduleattr_set.get().patient_weight)
|
|
96
|
+
pat_mass_source = "extracted"
|
|
97
|
+
except (ValueError, TypeError):
|
|
98
|
+
pat_mass = 73.2
|
|
99
|
+
|
|
100
|
+
if pat_mass == 0.0:
|
|
101
|
+
pat_mass = 73.2
|
|
102
|
+
pat_mass_source = "assumed"
|
|
103
|
+
|
|
104
|
+
pat_height_source = "assumed"
|
|
105
|
+
try:
|
|
106
|
+
pat_height = (
|
|
107
|
+
float(study.patientstudymoduleattr_set.get().patient_size) * 100
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
pat_height_source = "extracted"
|
|
111
|
+
except (ValueError, TypeError):
|
|
112
|
+
pat_height = 178.6
|
|
113
|
+
|
|
114
|
+
if pat_height == 0.0:
|
|
115
|
+
pat_height = 178.6
|
|
116
|
+
pat_height_source = "assumed"
|
|
117
|
+
|
|
118
|
+
ptr = None
|
|
119
|
+
orientation_modifier = None
|
|
120
|
+
try:
|
|
121
|
+
ptr_meaning = (
|
|
122
|
+
study.projectionxrayradiationdose_set.get()
|
|
123
|
+
.irradeventxraydata_set.all()[0]
|
|
124
|
+
.patient_table_relationship_cid.code_meaning.lower()
|
|
125
|
+
)
|
|
126
|
+
if ptr_meaning in "headfirst":
|
|
127
|
+
ptr = "H"
|
|
128
|
+
elif ptr_meaning in "feet-first":
|
|
129
|
+
ptr = "F"
|
|
130
|
+
else:
|
|
131
|
+
logger.info(
|
|
132
|
+
f"Study PK {study_pk}: Patient table relationship not recognised ({ptr_meaning}). "
|
|
133
|
+
f"Assuming head first."
|
|
134
|
+
)
|
|
135
|
+
except AttributeError:
|
|
136
|
+
logger.info(
|
|
137
|
+
f"Study PK {study_pk}: Patient table relationship not found. Assuming head first."
|
|
138
|
+
)
|
|
139
|
+
except IndexError:
|
|
140
|
+
logger.info(
|
|
141
|
+
f"Study PK {study_pk}: No irradiation event x-ray data found. Assuming head first."
|
|
142
|
+
)
|
|
143
|
+
try:
|
|
144
|
+
orientation_modifier_meaning = (
|
|
145
|
+
study.projectionxrayradiationdose_set.get()
|
|
146
|
+
.irradeventxraydata_set.all()[0]
|
|
147
|
+
.patient_orientation_modifier_cid.code_meaning.lower()
|
|
148
|
+
)
|
|
149
|
+
if orientation_modifier_meaning in "supine":
|
|
150
|
+
orientation_modifier = "S"
|
|
151
|
+
elif orientation_modifier_meaning in "prone":
|
|
152
|
+
orientation_modifier = "P"
|
|
153
|
+
else:
|
|
154
|
+
logger.info(
|
|
155
|
+
f"Study PK {study_pk}: Orientation modifier not recognised ({orientation_modifier_meaning}). "
|
|
156
|
+
f"Assuming supine."
|
|
157
|
+
)
|
|
158
|
+
except AttributeError:
|
|
159
|
+
logger.info(
|
|
160
|
+
f"Study PK {study_pk}: Orientation modifier not found. Assuming supine."
|
|
161
|
+
)
|
|
162
|
+
except IndexError:
|
|
163
|
+
logger.info(
|
|
164
|
+
f"Study PK {study_pk}: No irradiation event x-ray data found. Assuming supine."
|
|
165
|
+
)
|
|
166
|
+
if ptr and orientation_modifier:
|
|
167
|
+
pat_pos_source = "extracted"
|
|
168
|
+
pat_pos = ptr + "F" + orientation_modifier
|
|
169
|
+
elif ptr:
|
|
170
|
+
pat_pos_source = "supine assumed"
|
|
171
|
+
pat_pos = ptr + "FS"
|
|
172
|
+
elif orientation_modifier:
|
|
173
|
+
pat_pos_source = "head first assumed"
|
|
174
|
+
pat_pos = "HF" + orientation_modifier
|
|
175
|
+
else:
|
|
176
|
+
pat_pos_source = "assumed"
|
|
177
|
+
pat_pos = "HFS"
|
|
178
|
+
logger.debug(f"patPos is {pat_pos} and source is {pat_pos_source}")
|
|
179
|
+
|
|
180
|
+
my_exp_map = CalcExpMap(
|
|
181
|
+
phantom_type="3D",
|
|
182
|
+
pat_pos=pat_pos,
|
|
183
|
+
pat_mass=pat_mass,
|
|
184
|
+
pat_height=pat_height,
|
|
185
|
+
table_thick=0.5,
|
|
186
|
+
table_width=45.0,
|
|
187
|
+
table_length=150.0,
|
|
188
|
+
matt_thick=4.0,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
prefetch_set = {
|
|
192
|
+
"irradeventxraymechanicaldata_set",
|
|
193
|
+
"irradeventxraymechanicaldata_set__doserelateddistancemeasurements_set",
|
|
194
|
+
"irradeventxraysourcedata_set",
|
|
195
|
+
"irradeventxraysourcedata_set__kvp_set",
|
|
196
|
+
"irradeventxraysourcedata_set__xrayfilters_set",
|
|
197
|
+
}
|
|
198
|
+
all_irradiations = (
|
|
199
|
+
study.projectionxrayradiationdose_set.get()
|
|
200
|
+
.irradeventxraydata_set.prefetch_related(*prefetch_set)
|
|
201
|
+
.all()
|
|
202
|
+
)
|
|
203
|
+
num_irradiations = all_irradiations.count()
|
|
204
|
+
|
|
205
|
+
for count, irrad in enumerate(all_irradiations):
|
|
206
|
+
if background_task is not None:
|
|
207
|
+
background_task.info = (
|
|
208
|
+
f"Unit: {display_name} | "
|
|
209
|
+
f"PK: {study_pk} | Working on irradiation {count+1} of {num_irradiations}"
|
|
210
|
+
)
|
|
211
|
+
background_task.save()
|
|
212
|
+
|
|
213
|
+
try:
|
|
214
|
+
delta_x = (
|
|
215
|
+
float(
|
|
216
|
+
irrad.irradeventxraymechanicaldata_set.get()
|
|
217
|
+
.doserelateddistancemeasurements_set.get()
|
|
218
|
+
.table_longitudinal_position
|
|
219
|
+
)
|
|
220
|
+
/ 10.0
|
|
221
|
+
)
|
|
222
|
+
except (ObjectDoesNotExist, TypeError):
|
|
223
|
+
delta_x = 0.0
|
|
224
|
+
try:
|
|
225
|
+
delta_y = (
|
|
226
|
+
float(
|
|
227
|
+
irrad.irradeventxraymechanicaldata_set.get()
|
|
228
|
+
.doserelateddistancemeasurements_set.get()
|
|
229
|
+
.table_lateral_position
|
|
230
|
+
)
|
|
231
|
+
/ 10.0
|
|
232
|
+
)
|
|
233
|
+
except (ObjectDoesNotExist, TypeError):
|
|
234
|
+
delta_y = 0.0
|
|
235
|
+
try:
|
|
236
|
+
delta_z = (
|
|
237
|
+
float(
|
|
238
|
+
irrad.irradeventxraymechanicaldata_set.get()
|
|
239
|
+
.doserelateddistancemeasurements_set.get()
|
|
240
|
+
.table_height_position
|
|
241
|
+
)
|
|
242
|
+
/ 10.0
|
|
243
|
+
)
|
|
244
|
+
except (ObjectDoesNotExist, TypeError):
|
|
245
|
+
delta_z = 0.0
|
|
246
|
+
if irrad.irradeventxraymechanicaldata_set.get().positioner_primary_angle:
|
|
247
|
+
angle_x = float(
|
|
248
|
+
irrad.irradeventxraymechanicaldata_set.get().positioner_primary_angle
|
|
249
|
+
)
|
|
250
|
+
else:
|
|
251
|
+
angle_x = 0.0
|
|
252
|
+
try:
|
|
253
|
+
angle_y = float(
|
|
254
|
+
irrad.irradeventxraymechanicaldata_set.get().positioner_secondary_angle
|
|
255
|
+
)
|
|
256
|
+
except (ObjectDoesNotExist, TypeError):
|
|
257
|
+
angle_y = 0.0
|
|
258
|
+
try:
|
|
259
|
+
d_ref = (
|
|
260
|
+
float(
|
|
261
|
+
irrad.irradeventxraymechanicaldata_set.get()
|
|
262
|
+
.doserelateddistancemeasurements_set.get()
|
|
263
|
+
.distance_source_to_isocenter
|
|
264
|
+
)
|
|
265
|
+
/ 10.0
|
|
266
|
+
- 15.0
|
|
267
|
+
)
|
|
268
|
+
except (ObjectDoesNotExist, TypeError):
|
|
269
|
+
# This will result in failure to calculate skin dose map. Need a sensible default, or a lookup to a
|
|
270
|
+
# user-entered value
|
|
271
|
+
d_ref = None
|
|
272
|
+
try:
|
|
273
|
+
dap = float(irrad.dose_area_product)
|
|
274
|
+
except (ObjectDoesNotExist, TypeError):
|
|
275
|
+
dap = None
|
|
276
|
+
try:
|
|
277
|
+
ref_ak = float(irrad.irradeventxraysourcedata_set.get().dose_rp)
|
|
278
|
+
except (ObjectDoesNotExist, TypeError):
|
|
279
|
+
ref_ak = None
|
|
280
|
+
try:
|
|
281
|
+
kvp = np.mean(
|
|
282
|
+
irrad.irradeventxraysourcedata_set.get()
|
|
283
|
+
.kvp_set.all()
|
|
284
|
+
.exclude(kvp__isnull=True)
|
|
285
|
+
.exclude(kvp__exact=0)
|
|
286
|
+
.values_list("kvp", flat=True)
|
|
287
|
+
)
|
|
288
|
+
kvp = float(kvp)
|
|
289
|
+
if np.isnan(kvp):
|
|
290
|
+
kvp = None
|
|
291
|
+
except (ObjectDoesNotExist, TypeError):
|
|
292
|
+
kvp = None
|
|
293
|
+
|
|
294
|
+
filter_cu = 0.0
|
|
295
|
+
if irrad.irradeventxraysourcedata_set.get().xrayfilters_set.all():
|
|
296
|
+
for (
|
|
297
|
+
xray_filter
|
|
298
|
+
) in irrad.irradeventxraysourcedata_set.get().xrayfilters_set.all():
|
|
299
|
+
try:
|
|
300
|
+
if xray_filter.xray_filter_material.code_value == "C-127F9":
|
|
301
|
+
filter_cu += float(
|
|
302
|
+
xray_filter.xray_filter_thickness_minimum
|
|
303
|
+
)
|
|
304
|
+
except AttributeError:
|
|
305
|
+
pass
|
|
306
|
+
|
|
307
|
+
if irrad.irradiation_event_type:
|
|
308
|
+
run_type = irrad.irradiation_event_type.code_meaning
|
|
309
|
+
else:
|
|
310
|
+
run_type = None
|
|
311
|
+
try:
|
|
312
|
+
frames = float(
|
|
313
|
+
irrad.irradeventxraysourcedata_set.get().number_of_pulses
|
|
314
|
+
)
|
|
315
|
+
except TypeError:
|
|
316
|
+
try:
|
|
317
|
+
frames = float(
|
|
318
|
+
irrad.irradeventxraysourcedata_set.get().exposure_time
|
|
319
|
+
/ irrad.irradeventxraysourcedata_set.get()
|
|
320
|
+
.pulsewidth_set.get()
|
|
321
|
+
.pulse_width
|
|
322
|
+
)
|
|
323
|
+
except (ObjectDoesNotExist, TypeError, decimal.InvalidOperation):
|
|
324
|
+
frames = None
|
|
325
|
+
except ObjectDoesNotExist:
|
|
326
|
+
frames = None
|
|
327
|
+
try:
|
|
328
|
+
end_angle = float(
|
|
329
|
+
irrad.irradeventxraymechanicaldata_set.get().positioner_primary_end_angle
|
|
330
|
+
)
|
|
331
|
+
except (ObjectDoesNotExist, TypeError):
|
|
332
|
+
end_angle = None
|
|
333
|
+
if ref_ak and d_ref:
|
|
334
|
+
my_exp_map.add_view(
|
|
335
|
+
delta_x=delta_x,
|
|
336
|
+
delta_y=delta_y,
|
|
337
|
+
delta_z=delta_z,
|
|
338
|
+
angle_x=angle_x,
|
|
339
|
+
angle_y=angle_y,
|
|
340
|
+
d_ref=d_ref,
|
|
341
|
+
dap=dap,
|
|
342
|
+
ref_ak=ref_ak,
|
|
343
|
+
kvp=kvp,
|
|
344
|
+
filter_cu=filter_cu,
|
|
345
|
+
run_type=run_type,
|
|
346
|
+
frames=frames,
|
|
347
|
+
end_angle=end_angle,
|
|
348
|
+
pat_pos=pat_pos,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
if background_task is not None:
|
|
352
|
+
background_task.info = (
|
|
353
|
+
f"Unit: {display_name} | "
|
|
354
|
+
f"PK: {study_pk} | Study UID: {study.study_instance_uid.replace('.', '. ')}"
|
|
355
|
+
)
|
|
356
|
+
background_task.save()
|
|
357
|
+
|
|
358
|
+
# Flip the skin dose map left-right so the view is from the front
|
|
359
|
+
# my_exp_map.my_dose.fliplr()
|
|
360
|
+
my_exp_map.my_dose.total_dose = np.roll(
|
|
361
|
+
my_exp_map.my_dose.total_dose,
|
|
362
|
+
int(my_exp_map.phantom.phantom_flat_dist // 2),
|
|
363
|
+
axis=0,
|
|
364
|
+
)
|
|
365
|
+
try:
|
|
366
|
+
my_exp_map.my_dose.total_dose = np.rot90(my_exp_map.my_dose.total_dose)
|
|
367
|
+
except ValueError:
|
|
368
|
+
pass
|
|
369
|
+
try:
|
|
370
|
+
SkinDoseMapResults.objects.get(
|
|
371
|
+
general_study_module_attributes=study
|
|
372
|
+
).delete()
|
|
373
|
+
except ObjectDoesNotExist:
|
|
374
|
+
pass
|
|
375
|
+
# assume that calculation failed if max(peak_skin_dose) == 0 ==> set peak_skin_dose to None
|
|
376
|
+
max_skin_dose = np.max(my_exp_map.my_dose.total_dose, initial=0)
|
|
377
|
+
max_skin_dose = max_skin_dose if max_skin_dose > 0 else None
|
|
378
|
+
|
|
379
|
+
if max_skin_dose is None:
|
|
380
|
+
background_task.complete = True
|
|
381
|
+
background_task.completed_successfully = False
|
|
382
|
+
background_task.error = "Skin dose map calculation failed"
|
|
383
|
+
background_task.save()
|
|
384
|
+
return
|
|
385
|
+
|
|
386
|
+
try:
|
|
387
|
+
dap_fraction = my_exp_map.my_dose.dap_count / float(study.total_dap)
|
|
388
|
+
except ZeroDivisionError:
|
|
389
|
+
dap_fraction = 1.0
|
|
390
|
+
SkinDoseMapResults(
|
|
391
|
+
general_study_module_attributes=study,
|
|
392
|
+
patient_orientation=pat_pos,
|
|
393
|
+
patient_mass=pat_mass,
|
|
394
|
+
patient_mass_assumed=pat_mass_source,
|
|
395
|
+
patient_size_assumed=pat_height_source,
|
|
396
|
+
patient_orientation_assumed=pat_pos_source,
|
|
397
|
+
phantom_width=my_exp_map.phantom.phantom_width,
|
|
398
|
+
phantom_height=my_exp_map.phantom.phantom_height,
|
|
399
|
+
phantom_depth=my_exp_map.phantom.phantom_depth,
|
|
400
|
+
patient_size=pat_height,
|
|
401
|
+
skin_map_version=__skin_map_version__,
|
|
402
|
+
peak_skin_dose=max_skin_dose,
|
|
403
|
+
dap_fraction=dap_fraction,
|
|
404
|
+
).save()
|
|
405
|
+
return_structure = {
|
|
406
|
+
"skin_map": my_exp_map.my_dose.total_dose.flatten().tolist(),
|
|
407
|
+
"width": my_exp_map.phantom.width,
|
|
408
|
+
"height": my_exp_map.phantom.height,
|
|
409
|
+
"phantom_width": my_exp_map.phantom.phantom_width,
|
|
410
|
+
"phantom_height": my_exp_map.phantom.phantom_height,
|
|
411
|
+
"phantom_head_height": my_exp_map.phantom.phantom_head_height,
|
|
412
|
+
"phantom_head_radius": my_exp_map.phantom.phantom_head_radius,
|
|
413
|
+
"phantom_depth": my_exp_map.phantom.phantom_depth,
|
|
414
|
+
"phantom_flat_dist": my_exp_map.phantom.phantom_flat_dist,
|
|
415
|
+
"phantom_curved_dist": my_exp_map.phantom.phantom_curved_dist,
|
|
416
|
+
"patient_height": pat_height,
|
|
417
|
+
"patient_mass": pat_mass,
|
|
418
|
+
"patient_orientation": pat_pos,
|
|
419
|
+
"patient_height_source": pat_height_source,
|
|
420
|
+
"patient_mass_source": pat_mass_source,
|
|
421
|
+
"patient_orientation_source": pat_pos_source,
|
|
422
|
+
"fraction_DAP": dap_fraction,
|
|
423
|
+
"skin_map_version": __skin_map_version__,
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
# Save the return_structure as a pickle in a skin_maps sub-folder of the MEDIA_ROOT folder
|
|
427
|
+
save_openskin_structure(study, return_structure)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def skin_dose_maps_enabled_for_xray_system(study):
|
|
431
|
+
# Get all OpenSkinSafeList table entries that match the manufacturer and model name of the current study
|
|
432
|
+
entries = OpenSkinSafeList.objects.all().filter(
|
|
433
|
+
manufacturer=study.generalequipmentmoduleattr_set.get().manufacturer,
|
|
434
|
+
manufacturer_model_name=study.generalequipmentmoduleattr_set.get().manufacturer_model_name,
|
|
435
|
+
)
|
|
436
|
+
# Look for an entry which has a matching software version with the current study,
|
|
437
|
+
# or an entry where the software version is blank (any software version)
|
|
438
|
+
entry = False
|
|
439
|
+
for current_entry in entries:
|
|
440
|
+
if (
|
|
441
|
+
current_entry.software_version
|
|
442
|
+
== study.generalequipmentmoduleattr_set.get().software_versions
|
|
443
|
+
or current_entry.software_version is None
|
|
444
|
+
or not current_entry.software_version
|
|
445
|
+
):
|
|
446
|
+
entry = True
|
|
447
|
+
break
|
|
448
|
+
return entry
|