This is not, not, not medical software. Rather, it's something entirely thrown together in the course of a single evening for my own amusement. Do not use it to make any medical decisions. Do not use it in a professional environment. I make no claims whatsoever that the software is suitable for any use, of any kind, other than entertainment. I can assure you that I won't use it for any purpose other than amusement myself. I presume that there are laws or regulations in various jurisdictions to which software must conform to be suitable for medical usage, but I have not researched the matter, do not know what those laws and regulations may be, and unconditionally assume that this software does not comply with them. Rely only on medical professionals trained in the particular area of interest for medical advice, and don't listen to untrained lunkheads such as myself, even if they have respectable degrees in unrelated fields from respectable institutions.
I found myself in possession of two sets of my own Coronary CTA data, taken about a dozen years apart, and I developed a whim to do a side-by-side comparison of those two datasets.
Google's AI Assistant explained to me that medical-imaging data is universally stored in the so-called DICOM format, but that commonly-available image-viewing software does not display images in this format. In other words, medical imaging software is required for viewing.
It occurred to me that it might be possible to have an AI coding assistant create such a viewing program ... at least, one good enough for my single viewing task, without providing any of the identity protection, bullet-proofing, or bells and whistles — whatever they might be — that an actual medical viewer would need. Since I have recently been using Claude Code as a coding assistant, I chose to use it here too.
All of the files (software source code, documentation) presented here written by Claude Code (model Sonnet 5), with the sole exception being this README you're currently looking at, which I wrote because I couldn't stand not getting my 2¢ in. The entire development process took a single evening, literally, most of which I spent Googling and watching YouTube videos about how to read Coronary CTA imagery.
Aside: And I didn't manage in the end to learn how to identify the features of interest to me in the CTA data. An evening does not suffice. Consult a radiologist if you need that kind of expert evaluation!
For more information, such as installation instructions, look at Claude's own documentation in the README-claude file. Here's the executive summary:
- Two programs are provided:
ctviewer, which can view either a single DICOM dataset and render it as stack of 2D "slices", or else two DICOM datasets of 2D slices, shown side-by-side, perhaps of different resolutions but scaled to be visually comparable.ctviewer3d, which can render a single DICOM dataset as a true 3D model.
- The 2D software has a feature in which it can roughly mark up the imagery with what it thinks may be the names of the particular features ... at least if your data is Coronary CTA data. Neither Claude nor I have tried it, because it requires a license to use. There are both paid and free (academic) forms of the license, but I didn't feel like applying for it.
- If your dataset is something other than Coronary CTA data, or if it's Coronary CTA data which differs in format from my own, the software may or may not work for your data. I have no way to form an opinion about it one way or the other.
- Both programs are in the Python 3 language, and are cross-platform (Claude tells me), for Linux, Mac OS, or Windows. I've only tried it on Linux Mint myself.
Regardless of how you want to look at your data — a single dataset in 2D, comparison of two datasets in 2D, or a single dataset in 3D —, the first step after opening the viewer of your choice — ctviewer (2D) or ctviewer3d (3D) — is to actually load in a DICOM dataset. That's the File / Open Study Folder option on the main menu. For me so far, a "study folder" is one that contains a file called "DICOMDIR" and a folder with a lots of files in it that may or may not have names with the file extension ".dcm".
Once a study folder is open, you're presented with a list of the "series" which the dataset contains, perhaps something like this:
To me at least, the "descriptions" are just gobbledygook, but with a Coronary CTA, the series with the most available images is likely to be a nice candidate, so click on that one to select it. You'll see something like this:
Note how incredibly clever I've been by blurring out my name in the "Patient" field in the upper right. Now you don't know that the image is from my own heart. Ha ha!
I've marked a few of the image features I think I recognized by Googling — don't quote me! —, but more important are the viewing controls. The series being displayed isn't just a single flat image. This particular series is what's called an "axial view", and it consists of a set of flat images that are like horizontal slices through the heart. In this series, there are 353 slices in total. The slide-bar beneath the image allows you to move up or down in the "stack" of flat images, which is equivalent to moving up/down through the heart itself. The buttons marked "Prev" and "Next" are a more fine-grained control over this movement, and let you go up or down by just one slice at a time. You can also move up/down using the mouse's scroll-wheel.
The other visible controls are self-explanatory I think. One control you can't see is the brightness/image control. If you hold down the left-hand button on the mouse and move up/down, you'll find that it adjusts the image brightness, whereas if you move left/right it adjusts the image contrast. Although it doesn't appear in my screenshot above because I asked for it to be added while I was writing this blurb, there's also a "Reset W/L" button (next to the "Reset View" button) that resets the brightness/contrast to the default. (W/L stands for "Window Level", in case you're wondering.)
At this point, you have the option of opening a 2nd dataset and viewing it side-by-side versus the dataset you've already opened. That's done using the Compare option from the main menu. What follows is much like opening the first dataset, so I won't rehash that. One difference is that if the scans were made at different times, they probably enjoyed different technologies, so one of the datasets will have a higher graphical resolution and more slices. No problem, since ctviewer accounts for that.
Once the 2nd dataset is open, you'll see that some new controls have appeared underneath the main menu. The Match Brightness/Contrast button tries to adjust the right-hand image to conform to the left-hand image. The Auto-Align button does the same, but for the image scaling/rotation. These automated adjustments may still not produce a result to your liking, but you can use the conrols underneath the two images to fine-tune the settings as desired.
Once you think the two images are reasonably comparable, you can use the Lock Panes button to keep the left- and right-hand images sync'd as you move up/down through the image stack. As you do so, you may find that the match (in brightness, contrast, scaling, rotation) between the right- and left-images isn't quite what you wanted after all. That's okay, at any point you can unlock the images, reajust them, and then lock them back together. I've done all of those things in the screenshot below:
One thing to keep in mind in comparing Coronary CTA images taken at two different times is that the heart, one hopes, is beating in both of the datasets, but is certainly not synchronized between the two. So if you expected the two images to be identical, you are doomed to failure before you even start.
So that's what viewing stacks of 2D "slices" in the ctviewer program looks like. What about 3D imagery from the very same datasets? Use the program ctviewer3d for that. The initial experience is much the same, in that you have to open up the "study folder" and select a "series" from the provided list.
One slight wrinkle is that not all of the series available in the dataset are suitable for 3D viewing. For example, in the later of my own two datasets, the 1120-slice series we viewed in the screenshot above is not suitable. Nor is the 940-slice series provided in that same dataset. No worries, if you click on one of them, ctviewer3d will let you know it's not a valid choice. But the 280-slice series is suitable, so we can look at that one:
Well, that's nifty, if I do say so myself!
You'll see some new controls above the image. The "Preset" control has 3 settings. In addition to the CT Angio setting you see in the screenshot above, there are also "Bone",
and "Soft Tissue":
Darn clever, I think! Not my own doing, though, since Claude added these settings on its own without any feedback from me. But I do like them.
There's also an Opacity control, but that's pretty self-explatory.
You can rotate the 3D image by holding in the left-hand mouse button and moving the mouse. That's bit hard to understand and control ... not to mention being very slow on my 15-year-old computer. So there also numerical angular controls underneath the image that may or may not be easier to use.
Zooming, meanwhile, can be performed either using the control beneath the image, or else by using the scroll-wheel on the mouse.
Finaly, the 3D viewer has no side-by-side comparison option, largely I think because Claude expressed doubts about knowing how to handle stuff like sync'ing the two views, and I chose not to press the issue. However, if you think about it, you'll see that once you eliminate the notion of locking/sync'ing the two views, there's no particular reason you couldn't just open up two separate ctviewer3d instances, side-by-side, and load different datasets into them. That works.
There isn't any. If you find bugs, I'll ask Claude to fix them. If you ask for a feature that sounds interesting, perhaps I'll ask Claude to add it. If it doesn't become too burdensome.
But I literally cannot add any feature that's too fancy, because Claude would have to have your medical imaging data to test it. I don't want your imaging data, and if you're sensible, you shouldn't want to send it to me.
Here's what you can do, however: I've had Claude write up a specification for this software that (I instructed it) should be detailed enough to allow you (i.e., Claude) to write similar software from scratch. That documentation is the Specification.md file. So if you give an AI coding assistant that specification, along with the other contents of this repository, you should be able to add your own features (and fixes) to the software, without any involvement from me at all. Yay!
If you try that, feel free to let me know the results, and I'll read what you have to say if I'm not feeling too hungry or sleepy to attend to it.





