Skip to content

Added DICOM text SR assets and updated all operator test functions. #201

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

Merged
merged 12 commits into from
Nov 23, 2021

Conversation

MMelQin
Copy link
Collaborator

@MMelQin MMelQin commented Nov 23, 2021

This PR intends to add the DICOM text SR related assets as well as updating operator test functions,

  • add the Modelnfo class to encapsulate AI model info, per IHE AI Results (AIR) Rev 1.1, to be instantiated by the app.
  • add the EquipmentInfo class to encapsulate the DICOM instance equipment module, to be instantiated by the app.
  • add static function, write_common_modules, to writer common DICOM modules for all AI result instances.
  • Note the above 3 will be moved into Domain module, but for now, in the dicom_text_sr_writer_operator module.
  • Created dicom_text_sr_writer_operator, to accept AI textual results (classification results) and generated DICOM 3D SR instance.
  • Provided support for copying over tags from input DICOMSeries, as well as generating tags anew in the case of no original DICOMSeries as input.
  • Supported setting custom DICOM tags (limited to dict[str:str]), so that an app can customized the tags in the generated instance, e.g. SeriesDescription.
  • Supported StudySelectedSeries as input, though limited getting the first series; to be enhanced in later releases.
  • Added test() method for the new SR operator.
  • Updated existing operators' test() function to make it more robust.
  • Integrated the DICOM SR Writer Operator to the MedNIST Classifier example app, change the classifier to save in_memory result, while saving the result json file in the app's final output folder. The DICOM SR Writer gets the classifier in_memory result, and write the DICOM SR instance also in the app's final output folder, see the console output below,
mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ python3 mednist_classifier_monaideploy.py -i /home/mqin/src/monai-app-sdk/mednist_classifier_data/input -m /home/mqin/src/monai-app-sdk/mednist_classifier_data/classifier.zip -o output
Going to initiate execution of operator LoadPILOperator
Executing operator LoadPILOperator (Process ID: 10390, Operator ID: dd77d7e9-d809-4fb8-bc0c-10dced7a8ba0)
Done performing execution of operator LoadPILOperator

Going to initiate execution of operator MedNISTClassifierOperator
Executing operator MedNISTClassifierOperator (Process ID: 10390, Operator ID: 53e5bc37-00b6-409a-af18-44321d0d21a0)
Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at  /pytorch/c10/core/TensorImpl.h:1156.)
AbdomenCT
Done performing execution of operator MedNISTClassifierOperator

Going to initiate execution of operator DICOMTextSRWriterOperator
Executing operator DICOMTextSRWriterOperator (Process ID: 10390, Operator ID: 0a6e06d8-40e7-49d7-9534-ebb3cad5526f)
[2021-11-22 22:38:08,133] [INFO] (root) - Finished writing DICOM instance to file /home/mqin/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy/output/1.2.826.0.1.3680043.8.498.41451485589154548062724514663443495825_SR.dcm
Done performing execution of operator DICOMTextSRWriterOperator

mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ python3 mednist_classifier_monaideploy.py -i /home/mqin/src/monai-app-sdk/mednist_classifier_data/input -m /home/mqin/src/monai-app-sdk/mednist_classifier_data/classifier.zip -o output
Going to initiate execution of operator LoadPILOperator
Executing operator LoadPILOperator (Process ID: 10752, Operator ID: 1f9de980-a111-4339-9fb8-7f52df88c657)
Done performing execution of operator LoadPILOperator

Going to initiate execution of operator MedNISTClassifierOperator
Executing operator MedNISTClassifierOperator (Process ID: 10752, Operator ID: 07be39f6-9a4e-485a-a0f4-e54eb5b8b7ac)
Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at  /pytorch/c10/core/TensorImpl.h:1156.)
AbdomenCT
Done performing execution of operator MedNISTClassifierOperator

Going to initiate execution of operator DICOMTextSRWriterOperator
Executing operator DICOMTextSRWriterOperator (Process ID: 10752, Operator ID: 2c31e531-9534-403e-9463-eab8a9199794)
[2021-11-22 22:40:39,698] [INFO] (root) - Finished writing DICOM instance to file /home/mqin/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy/output/1.2.826.0.1.3680043.8.498.96453280060845449204658294728673910413_SR.dcm
Done performing execution of operator DICOMTextSRWriterOperator

mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ ls output/
1.2.826.0.1.3680043.8.498.41451485589154548062724514663443495825_SR.dcm  1.2.826.0.1.3680043.8.498.96453280060845449204658294728673910413_SR.dcm  output  output.json
mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ rm -r output/
mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ python3 mednist_classifier_monaideploy.py -i /home/mqin/src/monai-app-sdk/mednist_classifier_data/input -m /home/mqin/src/monai-app-sdk/mednist_classifier_data/classifier.zip -o output
Going to initiate execution of operator LoadPILOperator
Executing operator LoadPILOperator (Process ID: 10897, Operator ID: 7169336a-b5e0-4c7a-82db-4768bc57d63d)
Done performing execution of operator LoadPILOperator

Going to initiate execution of operator MedNISTClassifierOperator
Executing operator MedNISTClassifierOperator (Process ID: 10897, Operator ID: 07de4b37-c663-4c4e-9d95-2317afacd368)
Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at  /pytorch/c10/core/TensorImpl.h:1156.)
AbdomenCT
Done performing execution of operator MedNISTClassifierOperator

Going to initiate execution of operator DICOMTextSRWriterOperator
Executing operator DICOMTextSRWriterOperator (Process ID: 10897, Operator ID: 4106d4de-c0e1-4739-a76e-4808aeab3d3e)
[2021-11-22 22:41:03,807] [INFO] (root) - Finished writing DICOM instance to file /home/mqin/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy/output/1.2.826.0.1.3680043.8.498.11727638550238536439991540398727677966_SR.dcm
Done performing execution of operator DICOMTextSRWriterOperator

mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ ls output
1.2.826.0.1.3680043.8.498.11727638550238536439991540398727677966_SR.dcm  output.json
mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ cat output/output.json 
"AbdomenCT"
mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ dcmdump output/1.2.826.0.1.3680043.8.498.11727638550238536439991540398727677966_SR.dcm

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 208                                      #   4, 1 FileMetaInformationGroupLength
(0002,0001) OB 30\31                                    #   2, 1 FileMetaInformationVersion
(0002,0002) UI =Comprehensive3DSRStorage                #  30, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.826.0.1.3680043.8.498.11428616717435763037337295860364277466] #  64, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =LittleEndianImplicit                    #  18, 1 TransferSyntaxUID
(0002,0012) UI [1.2.40.0.13.1.1.1]                      #  18, 1 ImplementationClassUID
(0002,0013) SH [MONAI Deploy App SDK 0.2]               #  24, 1 ImplementationVersionName

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Implicit
(0008,0005) CS [ISO_IR 100]                             #  10, 1 SpecificCharacterSet
(0008,0012) DA [20211122]                               #   8, 1 InstanceCreationDate
(0008,0013) TM [224103]                                 #   6, 1 InstanceCreationTime
(0008,0016) UI =Comprehensive3DSRStorage                #  30, 1 SOPClassUID
(0008,0018) UI [1.2.826.0.1.3680043.8.498.11428616717435763037337295860364277466] #  64, 1 SOPInstanceUID
(0008,0020) DA [20211122]                               #   8, 1 StudyDate
(0008,0021) DA [20211122]                               #   8, 1 SeriesDate
(0008,0023) DA [20211122]                               #   8, 1 ContentDate
(0008,002a) DT [20211122224103]                         #  14, 1 AcquisitionDateTime
(0008,0030) TM [224103]                                 #   6, 1 StudyTime
(0008,0031) TM [224103]                                 #   6, 1 SeriesTime
(0008,0033) TM [224103]                                 #   6, 1 ContentTime
(0008,0050) SH (no value available)                     #   0, 0 AccessionNumber
(0008,0060) CS [SR]                                     #   2, 1 Modality
(0008,0070) LO [MOANI Deploy App SDK]                   #  20, 1 Manufacturer
(0008,0090) PN (no value available)                     #   0, 0 ReferringPhysicianName
(0008,1030) LO [AI results.]                            #  12, 1 StudyDescription
(0008,103e) LO [Not for clinical use. The result is research use only] #  54, 1 SeriesDescription
(0010,0010) PN (no value available)                     #   0, 0 PatientName
(0010,0020) LO (no value available)                     #   0, 0 PatientID
(0010,0021) LO (no value available)                     #   0, 0 IssuerOfPatientID
(0010,0030) DA (no value available)                     #   0, 0 PatientBirthDate
(0010,0040) CS (no value available)                     #   0, 0 PatientSex
(0018,0015) CS (no value available)                     #   0, 0 BodyPartExamined
(0020,000d) UI [1.2.826.0.1.3680043.8.498.34050712287586243027639325991381155954] #  64, 1 StudyInstanceUID
(0020,000e) UI [1.2.826.0.1.3680043.8.498.11727638550238536439991540398727677966] #  64, 1 SeriesInstanceUID
(0020,0010) SH [1]                                      #   2, 1 StudyID
(0020,0011) IS [1924]                                   #   4, 1 SeriesNumber
(0020,0013) IS [1]                                      #   2, 1 InstanceNumber
(0040,1001) SH (no value available)                     #   0, 0 RequestedProcedureID
(0040,a040) CS [TEXT]                                   #   4, 1 ValueType
(0040,a043) SQ (Sequence with explicit length #=1)      #  68, 1 ConceptNameCodeSequence
  (fffe,e000) na (Item with explicit length #=3)          #  60, 1 Item
    (0008,0100) SH [18748-4]                                #   8, 1 CodeValue
    (0008,0102) SH [LN]                                     #   2, 1 CodingSchemeDesignator
    (0008,0104) LO [Diagnostic Imaging Report]              #  26, 1 CodeMeaning
  (fffe,e00d) na (ItemDelimitationItem for re-encoding)   #   0, 0 ItemDelimitationItem
(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) #   0, 0 SequenceDelimitationItem
(0040,a160) UT [AbdomenCT]                              #  10, 1 TextValue
(0040,a493) CS [UNVERIFIED]                             #  10, 1 VerificationFlag
mqin@mingq-dt:~/src/monai-app-sdk/examples/apps/mednist_classifier_monaideploy$ 

@MMelQin
Copy link
Collaborator Author

MMelQin commented Nov 23, 2021

All checks, except the code coverage one, succeeded. Code coverage is allow to show failure, but both functional and integration testing was performed and succeeded.

  • standalone SR Writer operator testing (python3 dicom_text_sr_writer_operator.py) for with and without DICOM input succeeded.
  • integration testing in the MedNIST sample app succeeded.

So the PR is ready to be merged.

Copy link
Collaborator

@gigony gigony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Ming!
Looks good to me!

Copy link
Collaborator

@gigony gigony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ming!

On top of it, the following change would be needed before releasing.

--- a/docs/source/release_notes/index.md
+++ b/docs/source/release_notes/index.md
@@ -6,6 +6,14 @@
 

+## Version 0.2
+
+```{toctree}
+:maxdepth: 1
+
+v0.2.0
+```
+
 ## Version 0.1

### Series Selection Operator
This is to support the use case where whole DICOM studies are used as input to an AI inference application even though only specific series are applicable.

The selection rules are defined in JSON, allowing multiple selections, each with a set of matching conditions. The rules processing engine is implemented in the `DICOMSeriesSelectorOperator`, which itself is regarded as a base class with default implementation. More advanced rules and processing engine can be implemented in derived classes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The selection rules are defined in JSON, allowing multiple selections, each with a set of matching conditions. The rules processing engine is implemented in the `DICOMSeriesSelectorOperator`, which itself is regarded as a base class with default implementation. More advanced rules and processing engine can be implemented in derived classes.
The selection rules are defined in JSON, allowing multiple selections, each with a set of matching conditions. The rules processing engine is implemented in the `DICOMSeriesSelectorOperator`, which itself is regarded as a base class with the default implementation. More advanced rules and processing engines can be implemented in derived classes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was meant to say "rules processing engine"

Copy link
Collaborator Author

@MMelQin MMelQin Nov 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One second thought, rules can be redefined too, if the base class is not used for the new definition of rules.

Multiple instances of the series selection operators, each having its own rules, can be chained in a MONAI Deploy application. In part this is made possible by the new App SDK Domain classes which encapsulate the selected series in a DICOM study, and are used as the output of each series selection operator.

### DICOM Comprehensive Structured Report Writer
This is introduced to support generating DICOM SR SOP instances for AI classification result, and as such, the DICOM SR writer is limited to support textual results.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This is introduced to support generating DICOM SR SOP instances for AI classification result, and as such, the DICOM SR writer is limited to support textual results.
This is introduced to support generating DICOM SR SOP instances for the AI classification result, and as such, the DICOM SR writer is limited to support textual results.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed result to results.

This is introduced to support generating DICOM SR SOP instances for AI classification result, and as such, the DICOM SR writer is limited to support textual results.

The DICOM SR writer is implemented in `DICOMTextSRWriterOperator`, it
- loads AI result from in-memory object as well as from file path, with memory taking precedence
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- loads AI result from in-memory object as well as from file path, with memory taking precedence
- loads the AI result from the in-memory object as well as from file path, with memory taking precedence

The DICOM SR writer is implemented in `DICOMTextSRWriterOperator`, it
- loads AI result from in-memory object as well as from file path, with memory taking precedence
- copies applicable DICOM tags from the original DICOM series used as input for the inference application, as well as generating tags anew when there is no DICOM series provided.
- supports assigning DICOM tags via a dictionary with DICOM keywords and value, so that an application can customize the tags in the DICOM SR instance
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- supports assigning DICOM tags via a dictionary with DICOM keywords and value, so that an application can customize the tags in the DICOM SR instance
- supports assigning DICOM tags via a dictionary with DICOM keywords and values, so that an application can customize the tags in the DICOM SR instance

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value to their respective values, just to be specific.

### Updated example applications
- [The AI Spleen Segmentation](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/examples/apps/ai_spleen_seg_app) application updated to demonstrate the use of series selection rules
- [The MedNIST Classifier application](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/examples/apps/mednist_classifier_monaideploy) updated to demonstrate the use of DCIOM SR writing (without initial DICOM input)
- Updated are the main functions of the built-in [operators](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/monai/deploy/operators), which serve as examples on parsing the output objects
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Updated are the main functions of the built-in [operators](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/monai/deploy/operators), which serve as examples on parsing the output objects
- Updated are the main functions of the built-in [operators](https://github.com/Project-MONAI/monai-deploy-app-sdk/tree/main/monai/deploy/operators), which serve as examples of parsing the output objects

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to examples on how to parse, wanted to emphasize the how, as the Domain classes are getting more complex now, mingled with native classes from underlying packages.

@MMelQin MMelQin merged commit 0456678 into main Nov 23, 2021
@gigony gigony mentioned this pull request Nov 24, 2021
vikashg pushed a commit that referenced this pull request Nov 25, 2021
…201)

* Added DICOM text SR assets and updated all operator test functions.

Signed-off-by: mmelqin <[email protected]>

* Correcr style checker errors.

Signed-off-by: mmelqin <[email protected]>

* More style checker fix

Signed-off-by: mmelqin <[email protected]>

* More style checker fix to add Union[<type>, None]

Signed-off-by: mmelqin <[email protected]>

* Why the checker is so dumb, None for the typed object should be fine, and is handled.

Signed-off-by: mmelqin <[email protected]>

* Correct SR class name

Signed-off-by: mmelqin <[email protected]>

* Integrated DICOM SR Writer Operator to MedNIST classifier example

Signed-off-by: mmelqin <[email protected]>

* Correct typos in the comments

Signed-off-by: mmelqin <[email protected]>

* Add release note

Signed-off-by: mmelqin <[email protected]>

* Added updates to notebooks and fixed issues.

Signed-off-by: mmelqin <[email protected]>

* Cleaned up comment lines per review comments

Signed-off-by: mmelqin <[email protected]>

* Updated release_notes index.md, as well as release note itself

Signed-off-by: mmelqin <[email protected]>
@MMelQin MMelQin deleted the mqin/dicom_report branch February 3, 2025 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants