moloney / dcm Goto Github PK
View Code? Open in Web Editor NEWHigh level DICOM network and file operations. Provides CLI and Python async API.
License: MIT License
High level DICOM network and file operations. Provides CLI and Python async API.
License: MIT License
Hi,
is there a way to query for additional elements?
My dream would be that I can have a --level series
query with the ability to output additional elements on the following levels:
Or to have the possibility to query for additional fields per level query. Than I would query for all patients (+birth date, + sex), than the studies (+accession number) and than the series.
Thanks a lot for your time,
Joshy
Hi,
super nice project. I really like the cli and a query like dcm query pacs AccessionNumber=1234
works. Awesome!
In the above query would it be possible to print out some information on the series as well e.g. SeriesNumber, SeriesDescription?
Thanks a lot!
Cheers,
Joshy
Thanks so much for this package. I'm wondering if there is any support for working directly with DICOM files (i.e. sending to an AE).
Hello,
thank you for creating this awesome tool. I feel like it plugs in lots of features that are missing from pynetdicom (perhaps rightfully so because out of scope), like abstractions centered on typical use cases, async operations, etc.
Since I am considering to incorporate the tool in our lab's analysis pipelines, it would help to know the following:
Running the example with Python 3.9.7 throws the following error:
TypeError: DcmNode() takes no arguments
However, with version 3.7.11 it works as expected.
Is it possible to send a c_cancel, e.g., to gracefully interrupt the move of a series?
cnt = 1
async for instance_ds in local.retrieve(
remote,
query_res=QueryResult(QueryLevel.SERIES, data_sets=[query_dataset]),
report=retrieve_report
):
# process image
cnt += 1
if cnt == 15:
# cancel move
Why is the retrieve request so slow? @moloney
import asyncio
import time
from dcm._globals import QueryLevel
from dcm.net import DcmNode, LocalEntity
from dcm.node import RemoteNode
from pydicom import Dataset
async def main() -> None:
local = LocalEntity(DcmNode("localhost", "MY_AE_TITLE", 1111))
mypacs = RemoteNode("localhost", "CONQUESTSRV1", 5678)
query = Dataset()
query.StudyID = "433724515"
datasets = []
qr = await local.query(
mypacs,
query=query,
level=QueryLevel.IMAGE
)
start_perf_count = time.perf_counter()
async for ds in local.retrieve(remote=mypacs, query_res=qr):
datasets.append(ds)
print(f"Datasets length: {len(datasets)}, perf counter time: {time.perf_counter() - start_perf_count}")
if __name__ == "__main__":
asyncio.run(main())
Output: Datasets length: 384, perf counter time: 9.486925958000938
import time
from typing import List
from pydicom.dataset import Dataset
from pynetdicom import AE, evt, sop_class, StoragePresentationContexts
from pydicom.uid import ImplicitVRLittleEndian
class DicomClient:
def __init__(self, hostname, port, ae_title):
self.port = port
self.hostname = hostname
self.ae_title = ae_title
def fetch(self, datasets: List[Dataset]):
def handle_store(event):
dataset = event.dataset
dataset.file_meta = event.file_meta
datasets.append(dataset)
return 0x0000
handlers = [(evt.EVT_C_STORE, handle_store)]
ae = AE(ae_title=self.ae_title)
ae.add_requested_context(
sop_class._QR_CLASSES["PatientRootQueryRetrieveInformationModelMove"],
ImplicitVRLittleEndian
)
ae.supported_contexts = StoragePresentationContexts
scp = ae.start_server(("127.0.0.1", 1111), block=False, evt_handlers=handlers)
ds = Dataset()
ds.QueryRetrieveLevel = "IMAGE"
ds.StudyID = "433724515"
assoc = ae.associate(
addr=self.hostname,
port=self.port,
ae_title=self.ae_title,
evt_handlers=handlers
)
if assoc.is_established:
responses = assoc.send_c_move(
ds,
"MY_AE_TITLE",
sop_class._QR_CLASSES["PatientRootQueryRetrieveInformationModelMove"]
)
"""
for (status, _) in responses:
if status:
pass
else:
print('Connection timed out, was aborted or received invalid response')
"""
assoc.release()
else:
print('Association rejected, aborted or never connected')
scp.shutdown()
def main():
client = DicomClient(
hostname="localhost",
port=5678,
ae_title="CONQUESTSRV1"
)
datasets = []
start_perf_count = time.perf_counter()
client.fetch(datasets=datasets)
print(f"Datasets length: {len(datasets)}, perf counter time: {time.perf_counter() - start_perf_count}")
if __name__ == "__main__":
main()
Output: Datasets length: 384, perf counter time: 2.612817499997618
Hi @moloney,
I like what you've done here, making an asyncio wrapper around pynetdicom. Might you consider providing a license file for this software, eg Apache-2.0 as is used by PyMedPhys (https://github.com/pymedphys/pymedphys/blob/main/LICENSE)?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.