commontk / CTK

A set of common support code for medical imaging, surgical navigation, and related purposes.
https://commontk.org
Apache License 2.0
864 stars 492 forks source link

Roadmap list of issues/enhancements for Visual DICOM Browser #1162

Open Punzo opened 10 months ago

Punzo commented 10 months ago

RoadMap (items are not listed in priority):

long-termENH:

UI customization:

Issues and minor ENH:

Logic:

Settings:

Visual browser UI: Patient selection:

Filtering:

Thumbnails && series widgets:

Error report:

ctkDICOMVisualBrowser application:

Reference PR:

Punzo commented 10 months ago
  • Huge amount of DICOM communication log is printed on the console. It can cause very significant delays, so the amount should be configurable (we can use DICOM/detailedLogging application settings value).

@lassoan this should already work, please try to disable DICOM/detailedLogging in the Slicer settings.

Also, the messages should not be dumped to the console but it should be shown in the job list (maybe some messages, e.g., warnings/errors could be also logged in the application log)

yes I agree, this is also described in other points.

Punzo commented 9 months ago

For reference: Error report is addressed in the following PR:

jcfr commented 9 months ago
Punzo commented 9 months ago

I have done my last edit. @lassoan it would be nice if you can review (specifically the intial sentence regarding the "patient exploration tool").

Punzo commented 9 months ago

@lassoan, thanks for the text edits and I have applied yout comments in https://hackmd.io/SFrAGE4CS8uSkI2YvDRKRg?both.

I am going to post it now on the Slicer forum

@jcfr can you remove or replace the images and videos (see below for the new ones) in https://github.com/commontk/CTK/pull/1165#issue-2078249761, please? thanks in advance

ScreenshotVisualDICOMBrowser ScreenshotSettings

https://github.com/commontk/CTK/assets/7985338/a0e362e7-858a-4e47-9298-8d00ae16a23b

VisualDICOMBrowserUML

lassoan commented 9 months ago

I am going to post it now on the Slicer forum

Is the feature included in today's Slicer Preview Release? If not then please wait. Also, for biggest impact, it may worth making the announcement on Tuesday (many people are not at their computers in the weekend; Monday is often too busy). It would also allow us to do some internal testing with people we ask to have a look (Steve, Rudolf Bumm, ...).

Punzo commented 9 months ago

Is the feature included in today's Slicer Preview Release? If not then please wait.

yes!

image

Also, for biggest impact, it may worth making the announcement on Tuesday (many people are not at their computers in the weekend; Monday is often too busy). It would also allow us to do some internal testing with people we ask to have a look (Steve, Rudolf Bumm, ...).

ops sorry, I should have waited, I have already posted https://discourse.slicer.org/t/new-feature-visual-dicom-browser/33874 . I can delete it if you think it would be better.

lassoan commented 9 months ago

OK, no problem. There is some time before the weekend, so hopefully it will catch people's attention and they can find some time to try it and give feedback.

jcfr commented 9 months ago

We can also add a follow post on the topic on Tuesday to bring it to the top of the list. Something along those lines:

Raw:

Now that the feature has been available :sparkles: for a few day through the Slicer `Preview` package, let us know if you have any comments or suggestions.

Thanks again for your time :pray:

Rendered:

Now that the feature has been available :sparkles: for a few day through the Slicer Preview package, let us know if you have any comments or suggestions.

Thanks again for your time :pray:

Punzo commented 9 months ago

We can also add a follow post on the topic on Tuesday to bring it to the top of the list. Something along those lines:

Raw:

Now that the feature has been available :sparkles: for a few day through the Slicer `Preview` package, let us know if you have any comments or suggestions.

Thanks again for your time :pray:

Rendered:

Now that the feature has been available ✨ for a few day through the Slicer Preview package, let us know if you have any comments or suggestions.

Thanks again for your time 🙏

@jcfr @lassoan I was thinking that we may wait for the merge of https://github.com/commontk/CTK/pull/1184 (job list) to bring the post up to the list. Let me know.

Punzo commented 9 months ago

for reference:

current dev CTK branch https://github.com/Punzo/CTK/tree/visualDICOMBrowserENH

current dev Slicer branch https://github.com/Punzo/Slicer/tree/visualDICOMBrowserENH

mauigna06 commented 5 months ago

Could you please do the one below?

Study description should go in the ctk group title

Punzo commented 5 months ago

Could you please do the one below?

Study description should go in the ctk group title

sure!

Punzo commented 5 months ago

Could you please do the one below?

Study description should go in the ctk group title

Done in https://github.com/commontk/CTK/pull/1206/commits/7dca0f3fa0d12b4730f9027caa5a7225785eeef2

image image image

lassoan commented 5 months ago

I've been testing this and ran into an issue:

image

Punzo commented 5 months ago

I've been testing this and ran into an issue:

  • configure https://www.dicomserver.co.uk/ server
  • query using "a" in patient name
  • browse tabs, find a tab where there are a few normal-sized CT or MR scans
  • double-click on one of them => ERROR: it never loads
  • checked the job list, all jobs are cancelled
  • click the show/hide DICOM browser button to hide the browser and then click again to show it => ERROR: crash in ctkDICOMVisualBrowserWidgetPrivate::retrieveSeries() due to seriesItemWidget pointer is valid, but the memory position it points to contains a deleted object (dangling pointer)

ok, thanks for reporting. I will look into it now.

Punzo commented 5 months ago

I've been testing this and ran into an issue:

  • configure https://www.dicomserver.co.uk/ server
  • query using "a" in patient name
  • browse tabs, find a tab where there are a few normal-sized CT or MR scans
  • double-click on one of them => ERROR: it never loads
  • checked the job list, all jobs are cancelled
  • click the show/hide DICOM browser button to hide the browser and then click again to show it => ERROR: crash in ctkDICOMVisualBrowserWidgetPrivate::retrieveSeries() due to seriesItemWidget pointer is valid, but the memory position it points to contains a deleted object (dangling pointer)

ok, thanks for reporting. I will look into it now.

@lassoan fixed in https://github.com/commontk/CTK/pull/1206/commits/967de75d2653ad685d03fcee28a8f429a63dc0a5

There were few issues: 1) Not all the series widget status were handled properly in that specific logic -> causing hanging 2) some jobs were not stopped or restarted properly 3) missing a progress ApplicationModal dialog, I was giving the illusion that the user could freely click on the UI during this step. That was not possible since allowing the user to interact with the UI at this step would be possible only when we implement the streaming from series widget to slicer volumes. Therefore I have added a progress ApplicationModal dialog with cancel button.

I have implemented also this item from the roadmap (the issue was connected to this): While waiting for download of a complete sequence, we can still do some user actions, but not all. I suspect that it is because we pump the event loop with app->processEvents(), but that might be unintentional. We might want to call processEvents with flags that disable user interaction, or even better, show a model popup with a "Cancel" button.

please feel free to retest latest version! thanks for testing!

Punzo commented 5 months ago

please feel free to retest latest version! thanks for testing!

please note that I have just done a force push on last commit (https://github.com/commontk/CTK/pull/1206/commits/648f261a10e1a2d29c37d9a4e43249a84d4e6856)

lassoan commented 5 months ago

Thank you, I'm testing it now.

lassoan commented 5 months ago

Thanks a lot for the fixes, there are no more crashes or hangs!

But. When I click the "Show DICOM database" button to hide the browser then it's get hidden in a 1 second, good. When I click the "Show DICOM database" button to show the browser then it takes about 1 minute for the browser to appear, with this call stack when I stop at random times:

image

It seems that thumbnails are regenerated every time I show the browser. Probably in release mode it would not be so bad, but still, it is a lot of unnecessary work.

It is possible that these thumbnails are regenerated because thumbnail generation failed. I see these on the console:

E: no pixel data found in DICOM dataset
Rendering of DICOM image failed for thumbnail failed: Missing attribute
E: no pixel data found in DICOM dataset
Rendering of DICOM image failed for thumbnail failed: Missing attribute
E: no pixel data found in DICOM dataset
Rendering of DICOM image failed for thumbnail failed: Missing attribute
E: no pixel data found in DICOM dataset
Rendering of DICOM image failed for thumbnail failed: Missing attribute
E: no pixel data found in DICOM dataset
Rendering of DICOM image failed for thumbnail failed: Missing attribute
W: DcmItem: Length of element (01f1,1055) is not a multiple of 8 (VR=FD)
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result
W: processing MR image ... applying modality transform may create unexpected result

It also seems that these generated thumbnail are not saved to disk.

I've also noticed that the thumbnails are generated on the main thread. Since thumbnail generation can be really slow (it takes 10 seconds for this DICOM SEG) it would be nice to do it in background threads.

Punzo commented 5 months ago

@lassoan I have addressed the main issues with the thumbnails generation in https://github.com/commontk/CTK/pull/1206/commits/f59aef0e4b620f31919902209baeaf4794fcbd5b, plus few minor issues :

PERF: Implement thumbnail storage to disk to avoid re-rendering after series widget destruction.
PERF: Disable SEG rendering in thumbnails due to limited support and potential performance issues. Replace with a blank thumbnail featuring a document SVG.
BUG: Resolve issue hanging job termination when status is 'Queued'.
BUG: Address issue with FreezeJobsScheduling during shutdown.
BUG: Correct retry functionality when status icon on series widget is clicked.

Still need to work on the background thumbnail creation - ran out of time. But don't worry, it's on the task list for this issue.. i.e.:

rendering of thumbnail can be expensive and currently is done in the main thread. It would be nice to do it in background (i.e. create ctkDICOMThumbnailJob and ctkDICOMThumbnailWorker classes)

Feel free to test again, Thanks!

lassoan commented 5 months ago

Few minor things to improve on the very latest DICOM browser improvements:

Punzo commented 4 months ago

Few minor things to improve on the very latest DICOM browser improvements:

  • showing DICOM browser after it was hidden still takes about 5 seconds in debug mode (showing 25 patients from dicomserver.co.uk) - could we just show/hide the widget without rebuilding?
  • when I double-click on an image to load it and it stops retrieve of other series, then I get a bunch of "user stopped" jobs - OK. But then when I select all and retry then those "user stopped" jobs never go away. They seem to trigger some new jobs, but if those are successful then those stopped jobs still remain. It would be better to move them to a queued or in-progress state (they could maintain the entire job history, with all preivous errors, retries, etc.)
  • Maybe not an error, but those "user-stopped" jobs have various error, such as DUL Finite State Machine Error: No action defined, state 7 event 10 or Failed receiving DIMSE command: 0006:0205 DIMSE Caller passed in an illegal association but nothing indicates that the user cancelled these jobs (other than the Status: user-stopped). Is this normal?
  • When in 3D Slicer the DICOM browser is opened the first time then a window pops up for a fraction of a second and then disappears. This could be probably prevented by adding the window to some layout when it is created and first shown (or only show it when it is actually needed).

I have addressed the latter and opened a PR for Slicer to update CTK version. The first 3 I will address them whne I will be back from vacation.

Punzo commented 2 months ago
  • when I double-click on an image to load it and it stops retrieve of other series, then I get a bunch of "user stopped" jobs - OK. But then when I select all and retry then those "user stopped" jobs never go away. They seem to trigger some new jobs, but if those are successful then those stopped jobs still remain. It would be better to move them to a queued or in-progress state (they could maintain the entire job history, with all preivous errors, retries, etc.)
  • Maybe not an error, but those "user-stopped" jobs have various error, such as DUL Finite State Machine Error: No action defined, state 7 event 10 or Failed receiving DIMSE command: 0006:0205 DIMSE Caller passed in an illegal association but nothing indicates that the user cancelled these jobs (other than the Status: user-stopped). Is this normal?

Done in https://github.com/Punzo/CTK/commit/0c80562f7c48e5d6c3592aeb94bd4a4a916d34ab I will open a PR in CTK when I will have more ENH done

Punzo commented 2 months ago
  • showing DICOM browser after it was hidden still takes about 5 seconds in debug mode (showing 25 patients from dicomserver.co.uk) - could we just show/hide the widget without rebuilding?

I could not reproduce the timing issue, I have 30 patients from dicomserver.co.uk and the show/hide does not lag. Using debug mode and detailed logging in DICOM settings:

https://github.com/user-attachments/assets/d5626ea5-777c-481c-87cc-d109eda42692

In fact, when showing the visual DICOM browser widget, Slicer calls only self.dicomVisualBrowser.onShowPatients(), which do not perfom any query/retrieve and builds only the UI of the current selected patient widget. In addition for the series widgets of the selected patient, it uses the stored png files. Maybe there was an image giving issues to the thumbnail generator, which is still done in the main thread. It would be nice to get such series, if you manage to reproduce again the issue.

Anyway, in Slicer, it did not make sense to rebuild the UI of the visual dicom browser everytime. So now, I build it only once. Done in: https://github.com/Punzo/CTK/commit/6bc59dc1e19ef5ff918779377a87da345013d3b6 https://github.com/Punzo/Slicer/compare/Slicer%3ASlicer%3Amain...visualDICOMBrowserENH

Punzo commented 2 months ago
  • rendering of thumbnail can be expensive and currently is done in the main thread. It would be nice to do it in background (i.e. create ctkDICOMThumbnailJob and ctkDICOMThumbnailWorker classes)

Done in https://github.com/Punzo/CTK/commit/b9bc53df26c18ff79d85260f71514b6c83c0fb3e

this should also fix the 5 sec issue of the previous post:

showing DICOM browser after it was hidden still takes about 5 seconds in debug mode (showing 25 patients from dicomserver.co.uk) - could we just show/hide the widget without rebuilding?

Punzo commented 2 months ago

current PRs: https://github.com/commontk/CTK/pull/1217 and https://github.com/Slicer/Slicer/pull/7912

ENH: Refactor and clean up manual retry infrastructure ENH: Add job status logging to the detail logging window ENH: Enable thumbnail generation in worker processes BUG: Fix missing update of server settings UI BUG: Add missing Python wrapping methods for ctkJobDetail ENH: Enhance job logging for better traceability PERF: Optimize UI updates by directly calling component slots


To Do: Fix performance issues when allocating hundreds of jobs. In this case the: QMutexLocker locker(&this->QueueMutex); is now the bottleneck.

Strategy 1: Investigate all the current QMutexLocker. Are all really needed?

Strategy 2: substitute QMutexLocker with QReadLocker and QWriteLocker.

Strategy 3: Use tbb::concurrent_hash_map instead of a QMap if TBB is available (#ifdef). If not

Strategy 4 (only if the other strategies fail): We could drop the QThreadPool and instatiating QThreads by ourselves. Each QThread would have his own jobs/worker map (for each job there is a worker) and we would not need to lock anything. In this case, the scheduler would need to handle the load balacing of the threads.

Punzo commented 2 months ago

current PRs: #1217 and Slicer/Slicer#7912

ENH: Refactor and clean up manual retry infrastructure ENH: Add job status logging to the detail logging window ENH: Enable thumbnail generation in worker processes BUG: Fix missing update of server settings UI BUG: Add missing Python wrapping methods for ctkJobDetail ENH: Enhance job logging for better traceability PERF: Optimize UI updates by directly calling component slots

To Do: Fix performance issues when allocating hundreds of jobs. In this case the: QMutexLocker locker(&this->QueueMutex); is now the bottleneck.

Strategy 1: Investigate all the current QMutexLocker. Are all really needed?

Strategy 2: substitute QMutexLocker with QReadLocker and QWriteLocker.

Strategy 3: Use tbb::concurrent_hash_map instead of a QMap if TBB is available (#ifdef). If not

Strategy 4 (only if the other strategies fail): We could drop the QThreadPool and instatiating QThreads by ourselves. Each QThread would have his own jobs/worker map (for each job there is a worker) and we would not need to lock anything. In this case, the scheduler would need to handle the load balacing of the threads.

Fixed in https://github.com/commontk/CTK/pull/1218/commits/b204aa2f187c3b572a1b966b68c3408d6f90f116 by cleaning loops inside the mutex and using the QReadLocker/QWriteLocker instead of QMutexLocker

Tested with a patient with 33 studies and ~200 series