a python cli for generating medical physics reports

See the code Here

As part of the funding for my Ph.D. I work as sort of a junior diagnostic medical physicist in the department of Radiology at the University of Minnesota. My job is to perform state and federal physics tests on radiation producing equipment at any of the M Health Fairview sites across central Minnesota. As a trainee, I am not qualified to test CTs and MRIs (the fun ones) so I work on X-Ray rooms, C-Arms, and Bone Density scanners. The surveys are designed to test the radiation output and image quality of the equipment so that radiation is delivered to patients safely and imaging quality remains high.

As we perform the surveys we enter data given by our radiation detectors into Excel templates that are equipment type, manufacturer, and model specific. For each report I have to fill in a header with information about the equipment, like the ID and Serial Number, the Site, the Location within the site, the Manufacturer, the Model, etc. as well as information about myself and the general circumstances of the survey.

In addition, I am responsible for the storing, filing, and organization of the completed reports (~400 per year). To increase our ability to find completed reports I instituted a universal naming scheme for the reports which generally follows “IDNumber_Site_EquipmentType_Manufacturer-Model_ReportType_Date”. In practice this meant I was manually renaming the files from my colleagues at the end of each month and taking pains to name my reports correctly as well.

I was spending a significant chunk of time on naming and filling out the headers of the reports. Simply generating the template and filling out this standard info would take 5-15 minutes per piece of equipment. Who has time for that?

So I developed a command line interface (CLI) in Python to handle all of this for me. The general command is:

create_report ID_NUMBER [options]

Where options could be

Python has many good libraries for developing CLIs, including base python. I decided to use Click because it seems to be the most popular, and fit my use case nicely. When the command is invoked, the following steps occur:

  1. Find the equipment based on the ID number in an SQLite database
    • If the survey is an acceptance survey, the unit will not exist in the database yet, so the user is prompted for the necessary information.
  2. Determine the template needed given the equipment information found from the ID.
    • If the template doesn’t exist (I didn’t include CT because I don’t test them) throw an error and exit.
  3. Find the template and write the template header given the equipment information and user-supplied information from a configuration file.
  4. Save the template with the completed header to a folder with the form “Reports/Year/Month/Report.xlsx”, creating any folder that doesn’t already exist and utilizing the correct file name structure. Throw a warning if the report already exists and prompt the user to continue or cancel.

I implemented this with two classes: A unit class that contains and retrieves information about the specific equipment in the invocation, and a report_builder class that has methods for getting information about the specific report, writing information to the template, and saving the report with the proper filename.

In addition to Click I utilized the SQLite3 library (included in base python) and OpenPyXL to interact with the report template files. This tool has worked really well for me - saving me a ton of time and eliminating some fat-finger mistakes in file naming and header input. There are a few things that would make it even better:

  1. A tool to rename existing reports to the naming format listed above.
  2. Currently I store the equipment info in an SQLite database file (not committed to GitHub). Since this information can change over time - it would be ideal to have this information in a web-hosted database, and then to have a script that would update the offline db file used in the app, as most radiology departments I am in I won’t be able to be connected to the internet (blasted lead shielding).
  3. Expanding to the equipment types I don’t have in there yet (CT and MRI).
  4. Implement more rigorous testing procedures.

The GitHub repo for this project is located Here