comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 2144:9d77c935f2c3 dicom-sr

handling of pending referenced instances when loading DICOM-SR
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 16 Aug 2024 17:24:00 +0200
parents 1a02e758eaf4
children 743fa9c74443
comparison
equal deleted inserted replaced
2143:83efb01991c5 2144:9d77c935f2c3
153 WebViewerAction_CreateRectangleProbe, // New in 2.4 153 WebViewerAction_CreateRectangleProbe, // New in 2.4
154 WebViewerAction_CreateTextAnnotation // New in 2.4 154 WebViewerAction_CreateTextAnnotation // New in 2.4
155 }; 155 };
156 156
157 157
158 enum FramesCollectionType
159 {
160 FramesCollectionType_None,
161 FramesCollectionType_DicomSR
162 };
163
158 164
159 static OrthancStone::MouseAction ConvertWebViewerAction(int action) 165 static OrthancStone::MouseAction ConvertWebViewerAction(int action)
160 { 166 {
161 switch (action) 167 switch (action)
162 { 168 {
639 const std::string& seriesInstanceUid, 645 const std::string& seriesInstanceUid,
640 const std::string& pdf) = 0; 646 const std::string& pdf) = 0;
641 647
642 virtual void SignalVirtualSeriesThumbnailLoaded(const std::string& virtualSeriesId, 648 virtual void SignalVirtualSeriesThumbnailLoaded(const std::string& virtualSeriesId,
643 const std::string& jpeg) = 0; 649 const std::string& jpeg) = 0;
650
651 virtual void SignalDicomSRLoaded(const std::string& studyInstanceUid,
652 const std::string& seriesInstanceUid,
653 const std::string& sopInstanceUid) = 0;
644 }; 654 };
645 655
646 private: 656 private:
647 OrthancStone::ILoadersContext& context_; 657 OrthancStone::ILoadersContext& context_;
648 std::unique_ptr<IObserver> observer_; 658 std::unique_ptr<IObserver> observer_;
717 dicom.RemoveResource(seriesIdsToRemove[i]); 727 dicom.RemoveResource(seriesIdsToRemove[i]);
718 } 728 }
719 } 729 }
720 else if (payload.GetValue() == Orthanc::ResourceType_Instance) 730 else if (payload.GetValue() == Orthanc::ResourceType_Instance)
721 { 731 {
722 // This occurs if loading DICOM-SR 732 // This occurs if loading DICOM-SR: Show the DICOM-SR once all its referenced instances are loaded
723 733
724 // TODO - Hide/show DICOM-SR once they have been loaded 734 for (size_t i = 0; i < dicom.GetSize(); i++)
735 {
736 std::string studyInstanceUid, seriesInstanceUid, sopInstanceUid;
737 if (dicom.GetResource(i).LookupStringValue(studyInstanceUid, Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, false) &&
738 dicom.GetResource(i).LookupStringValue(seriesInstanceUid, Orthanc::DICOM_TAG_SERIES_INSTANCE_UID, false) &&
739 dicom.GetResource(i).LookupStringValue(sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false))
740 {
741 for (StructuredReports::const_iterator it = structuredReports_.begin(); it != structuredReports_.end(); ++it)
742 {
743 if (it->second->IsReferencedInstance(studyInstanceUid, seriesInstanceUid, sopInstanceUid))
744 {
745 bool complete = true;
746 for (size_t j = 0; j < it->second->GetReferencedInstancesCount(); j++)
747 {
748 std::string referencedStudyInstanceUid, referencedSeriesInstanceUid, referencedInstanceInstanceUid, sopClassUid;
749 it->second->GetReferencedInstance(referencedStudyInstanceUid, referencedSeriesInstanceUid, referencedInstanceInstanceUid, sopClassUid, j);
750 if (!instances_->HasResource(referencedInstanceInstanceUid))
751 {
752 complete = false;
753 break;
754 }
755 }
756
757 if (complete)
758 {
759 LOG(INFO) << "Loaded all the instances referred by DICOM-SR instance: " << sopInstanceUid;
760 if (observer_ != NULL)
761 {
762 observer_->SignalDicomSRLoaded(it->second->GetStudyInstanceUid(),
763 it->second->GetSeriesInstanceUid(),
764 it->second->GetSopInstanceUid());
765 }
766 }
767 }
768 }
769 }
770 }
725 } 771 }
726 772
727 if (payload.GetValue() == Orthanc::ResourceType_Study || 773 if (payload.GetValue() == Orthanc::ResourceType_Study ||
728 payload.GetValue() == Orthanc::ResourceType_Series) 774 payload.GetValue() == Orthanc::ResourceType_Series)
729 { 775 {
1164 { 1210 {
1165 return false; 1211 return false;
1166 } 1212 }
1167 } 1213 }
1168 1214
1169 IFramesCollection* GetSeriesFrames(const std::string& seriesInstanceUid) const 1215 IFramesCollection* GetSeriesFrames(FramesCollectionType& type,
1170 { 1216 const std::string& seriesInstanceUid) const
1217 {
1218 type = FramesCollectionType_None;
1219
1171 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid); 1220 OrthancStone::SeriesMetadataLoader::Accessor accessor(*metadataLoader_, seriesInstanceUid);
1172 1221
1173 if (accessor.IsComplete()) 1222 if (accessor.IsComplete())
1174 { 1223 {
1175 StructuredReports::const_iterator sr = structuredReports_.find(seriesInstanceUid); 1224 StructuredReports::const_iterator sr = structuredReports_.find(seriesInstanceUid);
1176 if (sr != structuredReports_.end()) 1225 if (sr != structuredReports_.end())
1177 { 1226 {
1178 assert(sr->second != NULL); 1227 assert(sr->second != NULL);
1228 type = FramesCollectionType_DicomSR;
1179 1229
1180 try 1230 try
1181 { 1231 {
1182 return new DicomStructuredReportFrames(*sr->second, *instances_); 1232 return new DicomStructuredReportFrames(*sr->second, *instances_);
1183 } 1233 }
1184 catch (Orthanc::OrthancException&) 1234 catch (Orthanc::OrthancException&)
1185 { 1235 {
1186 // TODO 1236 LOG(INFO) << "All the instances referenced by the DICOM-SR series \""
1187 LOG(ERROR) << "Instances of the DICOM-SR are not available yet"; 1237 << seriesInstanceUid << "\" are not available yet";
1188 return NULL; 1238 return NULL;
1189 } 1239 }
1190 } 1240 }
1191 1241
1192 std::unique_ptr<OrthancStone::SortedFrames> target(new OrthancStone::SortedFrames); 1242 std::unique_ptr<OrthancStone::SortedFrames> target(new OrthancStone::SortedFrames);
2473 // coordinates of the current texture, with (0,0) corresponding to 2523 // coordinates of the current texture, with (0,0) corresponding to
2474 // the center of the top-left pixel 2524 // the center of the top-left pixel
2475 boost::shared_ptr<OrthancStone::AnnotationsSceneLayer> stoneAnnotations_; 2525 boost::shared_ptr<OrthancStone::AnnotationsSceneLayer> stoneAnnotations_;
2476 2526
2477 bool linearInterpolation_; 2527 bool linearInterpolation_;
2528 std::string pendingSeriesInstanceUid_;
2478 2529
2479 2530
2480 void ScheduleNextPrefetch() 2531 void ScheduleNextPrefetch()
2481 { 2532 {
2482 while (!prefetchQueue_.empty()) 2533 while (!prefetchQueue_.empty())
3977 4028
3978 observer_->SignalSynchronizedBrowsing( 4029 observer_->SignalSynchronizedBrowsing(
3979 *this, current.GetOrigin() + synchronizationOffset_, current.GetNormal()); 4030 *this, current.GetOrigin() + synchronizationOffset_, current.GetNormal());
3980 } 4031 }
3981 } 4032 }
4033
4034
4035 void SetPendingSeriesInstanceUid(const std::string& seriesInstanceUid)
4036 {
4037 pendingSeriesInstanceUid_ = seriesInstanceUid;
4038 }
4039
4040
4041 void ClearPendingSeriesInstanceUid()
4042 {
4043 pendingSeriesInstanceUid_.clear();
4044 }
4045
4046
4047 const std::string& GetPendingSeriesInstanceUid() const
4048 {
4049 return pendingSeriesInstanceUid_;
4050 }
3982 }; 4051 };
3983 4052
3984 4053
3985 4054
3986 4055
4258 pointedPosition.GetX(), 4327 pointedPosition.GetX(),
4259 pointedPosition.GetY(), 4328 pointedPosition.GetY(),
4260 labelPosition.GetX(), 4329 labelPosition.GetX(),
4261 labelPosition.GetY() ); 4330 labelPosition.GetY() );
4262 } 4331 }
4332
4333 virtual void SignalDicomSRLoaded(const std::string& studyInstanceUid,
4334 const std::string& seriesInstanceUid,
4335 const std::string& sopInstanceUid) ORTHANC_OVERRIDE;
4263 }; 4336 };
4264 4337
4265 4338
4266 4339
4267 static OrthancStone::DicomSource source_; 4340 static OrthancStone::DicomSource source_;
4324 return viewport; 4397 return viewport;
4325 } 4398 }
4326 else 4399 else
4327 { 4400 {
4328 return found->second; 4401 return found->second;
4402 }
4403 }
4404
4405
4406 void WebAssemblyObserver::SignalDicomSRLoaded(const std::string& studyInstanceUid,
4407 const std::string& seriesInstanceUid,
4408 const std::string& sopInstanceUid)
4409 {
4410 for (Viewports::iterator it = allViewports_.begin(); it != allViewports_.end(); ++it)
4411 {
4412 if (it->second->GetPendingSeriesInstanceUid() == seriesInstanceUid)
4413 {
4414 it->second->ClearPendingSeriesInstanceUid();
4415
4416 FramesCollectionType type;
4417 std::unique_ptr<IFramesCollection> frames(GetResourcesLoader().GetSeriesFrames(type, seriesInstanceUid));
4418
4419 if (frames.get() != NULL)
4420 {
4421 it->second->SetFrames(frames.release());
4422 }
4423 }
4329 } 4424 }
4330 } 4425 }
4331 4426
4332 4427
4333 extern "C" 4428 extern "C"
4622 int LoadSeriesInViewport(const char* canvas, 4717 int LoadSeriesInViewport(const char* canvas,
4623 const char* seriesInstanceUid) 4718 const char* seriesInstanceUid)
4624 { 4719 {
4625 try 4720 try
4626 { 4721 {
4627 std::unique_ptr<IFramesCollection> frames(GetResourcesLoader().GetSeriesFrames(seriesInstanceUid)); 4722 FramesCollectionType type;
4723 std::unique_ptr<IFramesCollection> frames(GetResourcesLoader().GetSeriesFrames(type, seriesInstanceUid));
4628 4724
4629 if (frames.get() != NULL) 4725 if (frames.get() != NULL)
4630 { 4726 {
4727 GetViewport(canvas)->ClearPendingSeriesInstanceUid();
4631 GetViewport(canvas)->SetFrames(frames.release()); 4728 GetViewport(canvas)->SetFrames(frames.release());
4632 return 1; 4729 return 1;
4633 } 4730 }
4731 else if (type == FramesCollectionType_DicomSR)
4732 {
4733 GetViewport(canvas)->SetPendingSeriesInstanceUid(seriesInstanceUid);
4734 return 0;
4735 }
4634 else 4736 else
4635 { 4737 {
4738 GetViewport(canvas)->ClearPendingSeriesInstanceUid();
4636 return 0; 4739 return 0;
4637 } 4740 }
4638 } 4741 }
4639 EXTERN_CATCH_EXCEPTIONS; 4742 EXTERN_CATCH_EXCEPTIONS;
4640 return 0; 4743 return 0;