Comments (18)
Also, if you were open to it, part of what I would be hoping to achieve would be to make a Python wrapper around this library, and upload your package to the Python Package Index.
There is an amazing orchestration tool called CI Build Wheel (https://cibuildwheel.readthedocs.io/en/stable/) that can run with GitHub actions and create PyPI builds and releases across the range of OSes and architectures.
I'd be more than happy to build out the Python wrapper to DICOMautomation, as well as set up the automated build and release pipelines, and submit them as pull requests to your repo here.
As a first pass, the Python wrapper could be "DICOM in / DICOM out" and expose two functions that do one thing each:
import pydicom
import dicomautomaton
original_structure_dataset = pydicom.dcmread("path/to/dicom-rt-structure.dcm")
dilated_structure_dataset = dicomautomaton.dilate(
dataset=original_structure_dataset,
structure_names=["list", "of", "structure", "names"],
distance=3
)
eroded_structure_dataset = dicomautomaton.erode(
dataset=original_structure_dataset,
structure_names=["another", "list", "of", "names"],
distance=1
)
Or alternatively, a better API might be to collapse it into one function and mimic Shapely's buffer API:
import pydicom
import dicomautomaton
original_structure_dataset = pydicom.dcmread("path/to/dicom-rt-structure.dcm")
eroded_structure_dataset = dicomautomaton.buffer(
dataset=original_structure_dataset,
structure_names=["list", "of", "structure", "names"],
displacement=-3 # a positive value results in dilation, negative value, erosion
)
And, as a last alternative, if it is available within DICOMautomaton
currently, then we could expose different displacements along different axis, and different displacements in different directions. If that was the case, the API could look like:
import pydicom
import dicomautomaton
original_structure_dataset = pydicom.dcmread("path/to/dicom-rt-structure.dcm")
adjusted_structure_dataset = dicomautomaton.buffer(
dataset=original_structure_dataset,
structure_names=["list", "of", "structure", "names"],
# z, y, x order
# displacements = (
# (z- displacement, z+ displacement),
# (y- displacement, y+ displacement),
# (x- displacement, x+ displacement)
# )
displacements=((-2, 0), (3, 3), (3, 3))
)
from dicomautomaton.
Also, on this point within the docs:
DICOMautomaton
should NOT be used for clinical purposes. It is suitable only for research purposes or in a non-critical supporting role where outputs can be easily validated.While efforts have been made to verify integrity and validity of the code, no independent audit or review has been performed. The breadth of functionality would make it difficult to test all combinations of operations. We therefore rely on static analysis, code quality metrics, and a limited amount of integration testing for specific workflows.
I will include my own testing suite within the RAi product that covers the functionality utilised and verify that it is fit for purpose when used in combination with RAi's clinical product. In other words, I'll manage the regulatory burden of the specific functionality of the software I depend upon.
from dicomautomaton.
Hi @SimonBiggs. It's nice to hear from you. This sounds like a great idea!
Absolutely, feel free to use any of the code in DICOMautomaton in accordance with the license. You've mentioned above about verification, testing, and undergoing regulatory approval, but I would like to explicitly state that all of the code in DICOMautomaton should be effectively considered as software of unknown provenance. Please do not rely on it without thoroughly testing and determining fitness for your specific use-cases. No warranty is provided or implied. I know you're well aware, but I just wanted to reiterate!
The morphological operator implementation is currently a bit slow and strongly CPU-bound, so it might require some tweaking depending on your use-case. It runs on image masks, so the data flow is: (1) contours -> mask, (2) erode/dilate mask, (3) mask -> contours. If no CT images are available, a synthetic mask can be created with arbitrary resolution. It works reasonable well for moderate distances (e.g., 1-10 mm), but can be inaccurate for smaller distances and annoyingly slow for larger distances. There is a clear accuracy-speed tradeoff which would be more comfortably served by increasing mask resolution using SIMD or GPU acceleration. My plan is to add this eventually, but my wishlist and TODO lists are quite long, so I can't commit to a timeline right now.
I would very much appreciate a python wrapper or interface, which will be extremely useful! I'm happy to help facilitate this development. I recently revisited the idea and got stuck in the evaluation stage, trying to pick the best approach. Your expertise would help tremendously!!
from dicomautomaton.
Another quick thought: I'm not sure what exactly you have planned, but if you're going to apply morphological operators to the output of image segmentation, it will be easiest to apply them directly to the mask images. This will avoid the initial conversion from contour -> mask.
from dicomautomaton.
Absolutely, feel free to use any of the code in DICOMautomaton in accordance with the license.
Thanks @hdclark 🙂
but I would like to explicitly state that all of the code in DICOMautomaton should be effectively considered as software of unknown provenance.
Yup, most definitely. It'd be SOUP all the way.
the data flow is: (1) contours -> mask, (2) erode/dilate mask, (3) mask -> contours. ... It works reasonable well for moderate distances (e.g., 1-10 mm), but can be inaccurate for smaller distances and annoyingly slow for larger distances.
I was also reaching out to the developer over at PyGEL, and they have an approach where they create a mesh using a variation of Dual Contouring and then use distance fields from that mesh in order to undergo erosion or dilation:
janba/GEL#59
I think there might be value in pulling them both into a Python API and exposing both approaches, and then I can test the two approaches against each other under a range of various known solution cases.
What are your thoughts on an approach like that?
I would very much appreciate a python wrapper or interface, which will be extremely useful! I'm happy to help facilitate this development. I recently revisited the idea and got stuck in the evaluation stage, trying to pick the best approach. Your expertise would help tremendously!!
It would be my pleasure 🙂
Another quick thought: I'm not sure what exactly you have planned, but if you're going to apply morphological operators to the output of image segmentation, it will be easiest to apply them directly to the mask images. This will avoid the initial conversion from contour -> mask.
Yup, that is true. But I do want to also support people building structures as combinations of other structures (potentially after they've been dilated). Here's an example config I'm looking to be able to support:
from dicomautomaton.
from dicomautomaton.
I'm guessing that eroding/dilating meshes directly will be more precise but posibly slower than the mask-based approach
Given the masks are being produced via 3D UNet AI inference, I suspect that the erosion / dilation code won't be the bottleneck. So as long as the speed isn't a significant issue I'm certainly more interested in correctness.
Pulling in both libraries would still be my preference as that equips us into the future.
Do you have a preference on the name of the Python library?
- dicomaton
- dicomautomaton
- pydicomautomaton
And I suspect the best place for its code to reside would be within this same repo. Would that work with you?
Potentially all of the Python code could sit within a py
directory?
And, would you be okay with having GEL be included as a part of the build? Or would you prefer I do that in a separate package?
from dicomautomaton.
from dicomautomaton.
Shorter is certainly better with being able to import it. The DCMA name has quite unfortunate alternative connotations:
https://www.dmca.com/FAQ/What-is-a-DMCA-Takedown
One letter swapped, but a google search still finds that when searching for DCMA
from dicomautomaton.
from dicomautomaton.
Maybe best to just go for pydicomautomaton then?
It does feel a little too similar to the pydicom
library (https://github.com/pydicom/pydicom). There's also no real harm in calling it dicomautomaton or dicomaton without the py. At the end of the day if you're downloading the python version you do know what you're getting (don't need py in front of it to tell you that...)
from dicomautomaton.
from dicomautomaton.
Haha, all good. I think "dicomaton" is cool, but it's not what you're naming is already, so I'll go with the python package dicomautomaton unless you object?
from dicomautomaton.
👍
from dicomautomaton.
Alrighty 🙂, we have a placeholder PyPI package:
https://pypi.org/project/dicomautomaton/
When you get the chance would you be able to make a PyPI account and I'll make you an owner of that package.
from dicomautomaton.
from dicomautomaton.
I've registered using the handle 'hdclark'.
from dicomautomaton.
I've registered using the handle 'hdclark'.
Beautiful. You've been added as owner 🙂
from dicomautomaton.
Related Issues (6)
- Meet @ICCR HOT 8
- WASI HOT 11
- Plausibility of including DICOMautomaton with PyMedPhys HOT 2
- Add screenshots HOT 8
- Proposed "Hello World" HOT 31
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dicomautomaton.