Week 7: My Wildest Dreams Became Real
April 23, 2023
I’m not gonna lie: today was one of the best days I’ve had in a while. Why? Because despite being mentally, emotionally, and physically drained from my shifts at Starbucks which seem to grow longer and more frequent by the day, I hit a significant milestone in my senior project. How significant, you might ask? Well, to put it simply, it’s one that’s finally got me seeing the long-awaited daylight at the end of the tunnel darker than the night sky at midnight that is my senior project. But enough with the puns–let’s get into this week’s updates.
Part 1: An Unfortunate Typo
So as a quick recap from last week, I was trying to deconvolve stains from one normal patch and one patch containing pen markings and then combine the separated stains. While I was able to do so perfectly with the normal patch, I ran into a bit of an issue with the pen marking patch, as you can see below:
Long story short, this was definitely not the result I was hoping to achieve. What really puzzled me was where the bright red color was coming from, since none of the individual images that I was combining exhibited this color. I spent hours upon hours trying to find the solution, even going so far as to examine the arrays containing image data to see if I could notice anything that seemed off:
With no luck, I read through my code again to see if it made logical sense. And then, I saw it:
This is the code I was using to recombine the separated stains from the pen marking patch and display the resulting image. I say was because looking at this code, I noticed something quite peculiar in the first line. Namely, it seemed as though I was reading the HED (Hematoxylin, Eosin, & DAB) image as an RGB image and converting it to HED format again, when I intended to do the opposite: read the HED image as a HED image and convert it to RGB.
Still in shock that all of this pain and suffering could have been because of a simple typo, I switched out “rgb2hed” with “hed2rgb,” the function I was supposed to be using, and viewed the resulting image with bated breath:
Upon seeing this, I became very, very excited. Because it finally seemed that my code was producing the results I was expecting it to. Why? For reference, here are the separated images that were combined to produce this image:
The resulting image above with the combined stains finally looked a lot like what I would expect an image that combined the separated hematoxylin, eosin, and DAB stains to look like. Goodbye, weird red image that was single-handedly responsible for endless amounts of frustration and keyboard smashing on my part.
Part 2: A Fortunate GitHub Issue Page Encounter
Now, I had one final hurdle left to overcome: excluding DAB from my resulting image with recombined stains. Since I’m dealing with hematoxylin & eosin (H&E) images, there is actually no DAB channel present in any of the images I’m using. However, since the library I’m using for deconvolution (scikit-image) is coded to display H, E, and D (I’m too lazy to type out the full names over and over again) channels together regardless of whether they actually exist or not in the input image, it seemingly viewed the brown background on the original image as representative of the DAB channel, resulting in the image you see above. Furthermore, the functions to convert RGB to HED and HED to RGB contain all 3 stains by default, so there’s no easy way to exclude DAB without modifying scikit-image’s source code.
So, I began searching for another way to exclude DAB. After spending hours upon hours reading research papers and scientific articles and Stack Overflow pages and lots of documentation about how HED images are structured and how the conversion process between RGB and HED works, I came upon a relatively obscure GitHub issue page on the scikit-image repository about someone with a distantly related issue to mine. Scrolling through, I felt as though I struck gold during the Gold Rush as I read this part of the page:
With this code, I’d theoretically be able to manually set the DAB channel to 0 (producing a blank image) earlier in the process, so only the H and E channels would be visible on the resulting image with combined stains. After revising my code, I ran stain deconvolution again:
Awesome, I was able to remove the DAB channel successfully while preserving the data in the hematoxylin and eosin channels. Now, it was time to combine them. This was the moment I’d been waiting for for the past seven weeks of my work on this project. With a glimmer of hope that the end was finally near, I ran the last bit of code to combine the separated stains from the pen marking patch:
I did it! I finally did it. I was able to completely remove the presence of pen markings from this patch while preserving the original tissue data. While it does look like I lost a bit of visual clarity and color intensity of the stained tissue, I think it’s safe to say that I was able to prove my main hypothesis to be true upon comparing this processed patch to the raw patch:
It seems so surreal to be saying this after all of the setbacks and pitfalls I’ve faced thus far, but I’m proud to say that I’m finally out of the woods.
Now, after verifying that my code works with other patches as well (since I’ve only really been testing with the same two patches over and over again), it’s time to implement this code into the end-to-end patch processing pipeline that I began working on a few weeks ago. The end game for my project is finally in sight, and I’ve been imbued with a renewed sense of hope and excitement as I come close to finally wrapping my project up.
See you next week!
Citations
- Comic ©FoxTrot Comics By Bill Amend, Used Under The Educational Re-Use Policy From Www.Foxtrot.Com.