Fixing accumulated AGD and laterality for Hologic DBT¶
The code for extracting dose related information from Hologic digital breast tomosynthesis proprietary projection images object used an incorrect tag to extract the laterality of the image. As a result the accumulated AGD code didn’t work, so the accumulated AGD cell on the mammography summary sheets remained blank.
The code below allows the laterality to be derived automatically from the acquisition protocol name, if the protocol
name has R
or L
as the first letter. When this information is derived, the accumulated AGD is also calculated
per breast.
Back up your database¶
It is always best practice to backup your database before running code to edit your database:
- For PostgreSQL you can refer to Backup the database
- For a non-production SQLite3 database, simply make a copy of the database file
How to use the code¶
Create a new file in your Python OpenREM folder (the folder manage.py
is in). For example it could be called
fix_dbt_laterality.py
:
- Ubuntu linux:
/usr/local/lib/python2.7/dist-packages/openrem/fix_dbt_laterality.py
- Other linux:
/usr/lib/python2.7/site-packages/openrem/fix_dbt_laterality.py
- Linux virtualenv:
vitualenvfolder/lib/python2.7/site-packages/openrem/fix_dbt_laterality.py
- Windows:
C:\Python27\Lib\site-packages\openrem\fix_dbt_laterality.py
- Windows virtualenv:
virtualenvfolder\Lib\site-packages\openrem\fix_dbt_laterality.py
Copy and paste into the new file the code from below. You will need to edit the DISPLAY_NAME
to match the display
name you have configured for the Hologic DBT system that needs to be modified. If you are not sure what this is, go to
the home page of your OpenREM installation and see how the Hologic unit is listed there. You will not be able to copy
and paste from there as if you click on it it will load that page, and likewise on the summary list page. If you click
through to the study detail page, you will find the display name listed in the details there. See the
Display names and user-defined modalities documentation for more information.
If you are working on Linux, you may like to look at the brief tips on using nano
on the Nginx
Troubleshooting and tips section.
# -*- coding: utf-8 -*-
# Routine to fix missing laterality details for exposures extracted from Hologic DBT proprietary projection data objects
# Also retrospectively updates the accumulated average glandular dose fields that were previously missing due to lack
# of laterality.
#
# Contains hard coded DISPLAY_NAME that must be changed appropriately to identify the Hologic DBT system in your
# database.
# See https://bitbucket.org/openrem/openrem/issues/411
import os
import sys
import django
import logging
from django.core.exceptions import ObjectDoesNotExist
logger = logging.getLogger(__name__)
# setup django/OpenREM
basepath = os.path.dirname(__file__)
projectpath = os.path.abspath(os.path.join(basepath, ))
if projectpath not in sys.path:
sys.path.insert(1, projectpath)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openremproject.settings')
django.setup()
from remapp.models import IrradEventXRayData
from remapp.tools.get_values import get_or_create_cid
# ******************************************************
# Update the DISPLAY_NAME
DISPLAY_NAME = "Display name of my Hologic"
# ******************************************************
def _accumulatedxraydose(proj):
"""
Borrowed from mam.py
Creates an AccumXRayDose table entry
:param proj: Projection x-ray radiation dose database entry
:return: Nothing
"""
from remapp.models import AccumXRayDose, AccumMammographyXRayDose
from remapp.tools.get_values import get_or_create_cid
accum = AccumXRayDose.objects.create(projection_xray_radiation_dose=proj)
accum.acquisition_plane = get_or_create_cid('113622', 'Single Plane')
accum.save()
accummam = AccumMammographyXRayDose.objects.create(accumulated_xray_dose=accum)
accummam.accumulated_average_glandular_dose = 0.0
accummam.save()
def _accumulatedmammo_update(event): # TID 10005
"""
Borrowed from mam.py
Updates the accumulated average glandular dose tables on a per-breast basis
:param event: Irradiation event database entry
:return: Nothing
"""
from remapp.tools.get_values import get_or_create_cid
from remapp.models import AccumMammographyXRayDose
try:
accum = event.projection_xray_radiation_dose.accumxraydose_set.get()
except ObjectDoesNotExist:
print("No accumxraydose for event occurring at {0} in study no {1}".format(event.date_time_started,
event.projection_xray_radiation_dose.general_study_module_attributes.id))
_accumulatedxraydose(event.projection_xray_radiation_dose)
accum = event.projection_xray_radiation_dose.accumxraydose_set.get()
accummams = accum.accummammographyxraydose_set.all()
event_added = False
for accummam in accummams:
if not accummam.laterality:
if event.laterality.code_meaning == 'Right':
accummam.laterality = get_or_create_cid('T-04020', 'Right breast')
elif event.laterality.code_meaning == 'Left':
accummam.laterality = get_or_create_cid('T-04030', 'Left breast')
accummam.accumulated_average_glandular_dose += event.irradeventxraysourcedata_set.get(
).average_glandular_dose
accummam.save()
event_added = True
elif event.laterality.code_meaning in accummam.laterality.code_meaning:
accummam.accumulated_average_glandular_dose += event.irradeventxraysourcedata_set.get(
).average_glandular_dose
accummam.save()
event_added = True
if not event_added:
accummam = AccumMammographyXRayDose.objects.create(accumulated_xray_dose=accum)
if event.laterality.code_meaning == 'Right':
accummam.laterality = get_or_create_cid('T-04020', 'Right breast')
elif event.laterality.code_meaning == 'Left':
accummam.laterality = get_or_create_cid('T-04030', 'Left breast')
accummam.accumulated_average_glandular_dose = event.irradeventxraysourcedata_set.get().average_glandular_dose
accummam.save()
accummam.save()
events = IrradEventXRayData.objects.filter(
projection_xray_radiation_dose__general_study_module_attributes__generalequipmentmoduleattr__unique_equipment_name__display_name__exact=DISPLAY_NAME)
events_r = events.filter(laterality__code_meaning__exact=u"Right")
events_l = events.filter(laterality__code_meaning__exact=u"Left")
events_n = events.filter(laterality__isnull=True)
print(u"Total events is {0}, of which {1} are Right, {2} are Left and {3} are null (remainder {4})".format(
events.count(), events_r.count(), events_l.count(), events_n.count(),
events.count() - events_r.count() - events_l.count() - events_n.count()))
for event in events_n:
if event.acquisition_protocol[0] == u'R':
event.laterality = get_or_create_cid('G-A100', 'Right')
event.save()
_accumulatedmammo_update(event)
elif event.acquisition_protocol[0] == u'L':
event.laterality = get_or_create_cid('G-A101', 'Left')
event.save()
_accumulatedmammo_update(event)
else:
print("Event acquisition protocol is {0} so we couldn't assign it left or right. Exam ID is {1}".format(
event.acquisition_protocol, event.projection_xray_radiation_dose.general_study_module_attributes.id))
events_r = events.filter(laterality__code_meaning__exact=u"Right")
events_l = events.filter(laterality__code_meaning__exact=u"Left")
events_n = events.filter(laterality__isnull=True)
print(u"Post update, total events is {0}, of which {1} are Right, {2} are Left and {3} are null (remainder {4})".format(
events.count(), events_r.count(), events_l.count(), events_n.count(),
events.count() - events_r.count() - events_l.count() - events_n.count()))
Run the fix¶
In a shell/command window, activate your virtualenv if you are using one, and change directory to the openrem folder:
- Ubuntu linux:
cd /usr/local/lib/python2.7/dist-packages/openrem/
- Other linux:
cd /usr/lib/python2.7/site-packages/openrem/
- Linux virtualenv:
cd virtualenvfolder/lib/python2.7/site-packages/openrem/
- Windows:
cd C:\Python27\Lib\site-packages\openrem\
- Windows virtualenv:
cd virtualenvfolder\Lib\site-packages\openrem\
Then:
python fix_dbt_laterality.py
This should generate the following response, with one message for each event that can’t be assigned laterality due to
the acquisition protocol name not starting with L
or R
:
Total events is 46410, of which 0 are Right, 0 are Left and 46410 are null (remainder 0)
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 184466
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 75963
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 75919
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 76004
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 83784
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 83784
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 84912
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 100765
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 110471
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 121500
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 121588
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 123462
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 137145
Event acquisition protocol is ACR Phantom Combo so we couldn't assign it left or right. Exam ID is 140563
Event acquisition protocol is Flat Field Tomo so we couldn't assign it left or right. Exam ID is 156826
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 165131
Event acquisition protocol is Flat Field Combo so we couldn't assign it left or right. Exam ID is 165486
Post update, total events is 46410, of which 23323 are Right, 23070 are Left and 17 are null (remainder 0)
The Exam ID referred to is the database ID, so if you look at a mammography exam in the web interface, you can change the Exam ID in the URL if you want to review that study.
Multiple Hologic units¶
If you have more than one unit that has studies that need fixing, simply change the DISPLAY_NAME
and run the code
again.