-
Notifications
You must be signed in to change notification settings - Fork 2
WIP - feat/extended-download-dicomweb #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
For this change, what I want is a generic interface for reading and writing DICOM data, so that it can read and write to any/all: You don't have to IMPLEMENT all of these, the only ones required right now are reading from DICOMweb and store to SDW file format, but it should go through a class interface to set things up. I would suggest testing with the SDW file for reading as well as writing, but the eventual goal is to have a single implementation that handles various endpoints. |
export class DicomAccess { public queryStudy?(studyInstanceUID: string): Promise; export class DicomStudyAccess { // Not quite sure yet what these will all return, as it should work for dimse public storeSeries(seriesAccess: SeriesAccess) { export abstract class DicomSeriesAccess { /** Stores the data in the preferred format for the given output location */ // Implementation for DICOMweb (separate file) export class DicomWebAccess extends DicomAccess { // Implementation of DicomAccess in terms of the library dicomweb-client // Dimse implementation (TODO later, but think about this one as to how to make it work consistently.) // File implementation public async queryStudy(studyInstanceUID: string) { export class FileStudyAccess extends DicomStudyAccess { |
…ecture and SDW output - Supports full DICOM study download via DICOMweb (WADO-RS) - Downloads study metadata, series metadata, instances, frames, and bulk data - Saves to local disk using SDW structure (Simple DICOM Web) - Implements pluggable DicomAccess interface (currently DICOMweb only) - Provides clear console logs for user feedback - Includes robust file organization and metadata serialization - Ready for future support of DIMSE and DICOMDIR backends
src/access/DicomAccess.js
Outdated
// Abstract base class for DICOM access implementations | ||
export class DicomAccess { | ||
static async createInstance(url, options) { | ||
if (url.startsWith("http")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to have at least two implementations - local dicomweb file system and dicomweb http as this should work for both types.
src/access/DicomWebSeriesAccess.js
Outdated
import * as dicomweb from "../dicomweb.js"; | ||
import { createDicomWebConfig, fixBulkDataURI } from "../utils/index.js"; | ||
|
||
const nonFrameSOPs = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please extract a method to test if an instance is a non image instance.
src/store/DicomStoreSDW.js
Outdated
import { saveJson } from "../utils/index.js"; | ||
import { DicomStoreAccess } from "./DicomStoreAccess.js"; | ||
|
||
export class DicomStoreSDW extends DicomStoreAccess { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The store should be a full, first class DicomAccess that can both read and write the file system, so I think you will have to make the additional methods public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean public on the DicomAccess, but unimplemented by default.
import fs from "fs"; | ||
import path from "path"; | ||
|
||
export function getDicomFilesFromDirectory(directory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use one of the directory tree scanners to get files in that directory and recursively, and unless the glob pattern is *.dcm, it should match everything - there might be an exclusion pattern, to exclude jpg, txt etc.
bin/cliDownload.js
Outdated
|
||
try { | ||
// Create access instance (currently supports only DICOMweb) | ||
console.log("🔌 Creating DICOM access instance..."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The download action should basically look like:
const access = await DicomAccess.createInstance(url, options);
const destination = await DicomAccess.createInstance(baseDir, options)
const studyAccess = await access.queryStudy()
const studyDest = await access.queryStudy({ create: true })
studyDest.writeStudy(studyAccess);
Then, internally studyAccess should have things iterated from/over that studyDest needs in order to write the study source.
That way, studyDest being a DICOMDIR containing part 10 files can be written to, as can a response to a DICOMweb part 10 query, or a DICOMweb query can all be written to independently of the source type.
src/access/DicomWebSeriesAccess.js
Outdated
this.metadata = metadata; | ||
|
||
// Containers to store queried data | ||
this.seriesInstanceUIDsMetadata = new Map(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't assume that everything gets read up front, instead read things as they are requested, grouping them into maps of objects as required with an async function doing the await on each item as it arrives.
🚀 Add
download
Command: Full DICOM Study Downloader via DICOMwebThis PR introduces a new CLI command
download
that downloads an entire DICOM study—including study, series, instances, frames, and bulkdata—from a DICOMweb-compliant service.The feature supports advanced functionality such as intelligent folder structuring, multi-frame handling, and JSON compression by default.
🚀 Features
🧪 Usage
node cli.js download https://d14fa38qiwhyfd.cloudfront.net/dicomweb \ --StudyInstanceUID 1.2.276.0.7230010.3.1.2.2155604110.4180.1021041295.21 \ --directory ~/dcmjs
🛠️ Options
<url>
http
)-S, --StudyInstanceUID
-d, --directory
./
)--zip-json
.json.gz
--debug
🗂️ Directory Structure (SDW Format)
🧱 Architecture
cliDownload.js
— CLI command registration and main workflowDicomAccess.js
— Abstract class defining a common interfaceDicomWebAccess.js
— Implements fetching data from DICOMwebDicomWebSeriesAccess.js
/DicomWebStudyAccess.js
— Handle specific study/series queriesDicomStoreSDW.js
— Stores metadata and binary data in a structured formatDicomStoreAccess.js
— Abstract base for pluggable storage backends📅 Future Plans