How I got here

  • B. Sc. in Physics
    • Medical Physics → Escape from ‘real’ physics
  • M. Sc. in Medical Physics (Monte Carlo simulations)

Programming

  • C64 Basic → Turbo Pascal → Fortran, C++, Perl, Python
  • Stuck on Python (with a sprinkling of C) for ~8 years now
  • Some commercial projects and some academic
  • Now spend my days writing software for clinic

About the Cancer Centre

  • Large 2 campus cancer centre
  • Chemo & Radiation Therapy
  • 4000 radiation patients/year — 75 000 individual treatments
  • Radiation Therapy
    • Rad Oncs
    • Treatment Planners
    • Therapists
    • Medical Physics

About Medical Physics

Medical Physics is about application of physics to medicine — radiation/x-rays, E&M, lasers, radionuclides, ultrasound etc.

Two biggest areas of activity:

  • Diagnostic Imaging
  • Radiation therapy

Numbers:

  • ~250 Medical Physicists in Canada (~7000 US, ~18 000 world)
  • 75% in hospitals w/ rest in .gov, .edu, .biz

About Medical Physics Department

Staff

  • 18 Medical Physicists
  • 2 Physics Associates
  • 4 Physics Techs
  • 7 Electronics/Machine Shop

Main areas of focus

  • Research & Development
  • Comissioning & Upkeep
  • Radiation Safety
  • Quality Assurance

~20 radiation treatment & imaging units

Typical Day On A Linear Accelerator

7:00
Therapists arrive & begin series of safety & dosimetry checks
8:00
Therapists completes checks & first treatment begins
18:00
Last treatment complete
18:00–?
Techs perform machine & patient QC

MLC IMG   MLC clip

Machine QC

To ensure accurate & safe treatment delivery, lots of QC activity

  • Protocols define tests required Daily, Weekly, Monthly, etc.
  • Tests range from simple :

    Does the warning light turn on when radiation beam is on?

    to complex:

    What is the radiation dose measured by an ion chamber in a 10cmx10cm at 5cm depth in water on the central axis?
  • Generates 200,000-250,000 individual test results / year performed by 120-150 people.

CNSC requires data to be stored for 7-10 years.

Keeping track of this data

Need a reliable, easy to use way to record & store this data

  • Original solution was to use paper forms
    • Takes up a lot of physical space
    • Incredibly tedious to review, data mine etc
    • Clinic wanted to go paperless in 2006...
  • Electronic solution
    • Commerical Software?
      • Software tightly coupled to vendors hardware
      • Expensive
      • Inflexible
  • Develop something in-house...

First Solution

When confronted with a problem, people often say:
‘I know...I'll use Excel!’
Now they have two problems.
– with apologies to Jamie Zawinski

QC Data Management System

What we had


  • 150+ spreadsheets
  • Fragmented data entry interfaces
  • Painful to review and approve
  • Painful to generate plots
  • Painful to add new tests
  • Multiple versions of same spreadsheet in the wild

What we wanted


  • Single point of access
  • Consistent data entry interface
  • Straightforward review and approval
  • Easy to look at data trends
  • Quick test additions & modifications

Let’s Build Something!

Perils of an in-house system

  • Previous attempts
  • We are not in the business of writing software!
  • Risky — Is this even going to work?
  • Very low “bus factor”
http://adamprescott.net/2012/12/04/lean-development-teams/

Mitigating the Risk

  • Develop prototype
    • See what works & what doesn't
    • What haven't you considered yet?
    • Allowed for time estimate
    • Proof of concept
  • Open Source
    • Give it away for free
    • Build a community of users
    • Mutual benefit for TOHCC & Medical Physics community
    • (Hopefully) increases the projects bus factor
  • Go for it!

QATrack+

QATrack+ is a web app built with Django

  • Dev started in Jan 2012, 1st pilot in Aug, full rollout Oct
  • Define lists of tests to be peformed at different frequencies
    • Trivial to modify or add new tests
  • Easy to use data entry interface
  • Helps with scheduling tests
  • Easy plotting of historical data
  • Makes daily test review much faster
  • Runs on a Microsoft Stack!
  • Open soure & now in use at 4 Canadian cancer centres

QATrack+ Demo

Django On Windows

Start investigating deploying Django...

"If you [run Django on] Windows you're going to have a bad time, trust me."

"Forced to run Django on Windows? That's about when I'd pack my shit and leave."

"The people I know who deploy Django on Windows [...] proxy IIS to CherryPy.

That's probably the sanest way."

- Jacob Kaplan Moss

Django on Windows

Calculated Tests In QATrack+

Users can define Python snippets for doing calculations

ftp = (temperature + 273.15)/295.15*(1.3332*760)/pressure
            
dose = ftp*p_ion*kq_sw*electrometer_reading
            
from scipy import stats

readings = [r1, r2, r3, r4, r5, r6, r7, r8, r9]
mus = [2, 3, 5, 11, 20, 50, 100, 200, 400]

ys = [m for r,m in zip(readings,mus) if r]
xs = [r for r in readings if r]

slope, intercept, r_value, p_value, std_err = stats.linregress(xs,ys)
dose_intercept = intercept
            

Calculated Tests Continued

Pseudo code for the view (Actual view is ~130 lines)

class CalculatedTest(JSONResponseMixin, View):

    def post(self, *args, **kwargs):

        #retrieve test calculation procedures from db
        calculated_tests = self.calculated_tests(self.request.POST.get("test_list")

        # set up a dict with current values of all tests (from POST data)
        calculation_context = self.calculation_context()

        #figure out the order the results need to be calculated on
        calculation_order = self.resolve_dependency_order(calculated_tests)

        results = {}

        for test in calculation_order:
            procedure = calculated_tests[test].procedure
            code = compile(procedure, "", "exec")
            exec code in calculation_context
            results[test] = calculation_context[test]

        return self.render_json_response(results)
            

Don't do this in public facing website!!!

Treatment Planning

Patient Treatment Process

1) Patient consult with physician

2) Rad onc assigns care plan

3) Treatment planner generates plan

4) Plan approval by physician

5) Plan QC by second planner

6) Plan QC by physicist + pt-spec. QA

7) Patient treatment

Operational Challenges

Treatment Planning

  • 400+ plans generated per month that need to be QA'd
  • No easy way to check if objectives being met
  • No formal record of why compromises were made
  • Hard to answer questions:
    • "How often do we hit all objectives for prostate plans?"
    • "What is dose delivered to the heart for all breast plans?"

How can we make this process better?

Software!

  • We want a simple means of tracking whether or not radiotherapy treatment plans are meeting clinical objectives
  • Requirements:
    • Quickly check whether objectives are being met
    • Simple/accessible web based user interface
    • Easily handle multiple Treatement Planning Systems
    • Keep record of careplans/objectives and results
    • Allow us to easily gather aggregate stats on plan quality

Plan QA Details

Open Source

Stack
  • IIS/CherryPy/SQL Server
  • Django
    • Tastypie
  • Numpy/Scipy
  • Fabric (for SSH)
  • Knockout.js / jQuery / underscore.js
Pluggable backends
  • Each backend module must expose two functions
    • def get_patient_ids(): ...
    • def get_patient_plans(patient_id): ...

Example Backend w/ Fabric

Fabric makes remote server access easy

def get_patient_ids():
    """return all available patient ID's on remote XiO server"""

    find_dvh = "find {0} -name {1}".format(settings.XIO_PATH, "rtog_dvh.dat")

    with fabric.api.settings(host_string="host", user="user", password="password"):
        results = fabric.api.run(find_dvh, stdout=StringIO.StringIO())

    return [clean_patient_id(x) for x in results.split()]

def get_patient_plans(patient_id):
    """return all available treatment plans for input patient"""

    dvh_path = "/{0}/{1}/rtog_dvh.dat".format(settings.XIO_DVH_ROOT, patient_id)

    with fabric.api.settings(host_string="host", user="user", password="password"):
        data = StringIO.StringIO()
        fabric.api.get(dvh_pat, local_path=data)
        dvh_dat = data.getvalue()

    return dvh_to_plan(dvh_dat)
        

Knockout.js

<div>
<p>
First name: <input data-bind='value: firstName' />
Last name: <input data-bind='value: lastName' />
<strong>Hello, <span data-bind='text: fullName'> </span>!</strong>
</p>
</div>

<script type="text/javascript">
var ViewModel = function(first, last) {
this.firstName = ko.observable(first);
this.lastName = ko.observable(last);
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
};
ko.applyBindings(new ViewModel("Planet", "Earth"));
</script>

First name: Last name: Hello, !

Plan QA Demo

<3 Python

We're using Python in a number of other tools as well:

  • data analysis (numpy/scipy/pandas/matplotlib)
  • patient anonymization (pydicom)
  • Desktop apps (wxPython, SQLAlchemy, Py2exe)
  • Other Django apps etc

  • What does Python give us?
    • Rapid iteration
    • Free!
    • Plays well with 0thers

Python is gaining traction in our department and Medical Physics in general. Great news!

Thank You!