comparison Samples/Sdl/Loader.cpp @ 764:f36a6f7e7bdf

cont
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 23 May 2019 12:54:10 +0200
parents 53167294d870
children f6438fdc447e
comparison
equal deleted inserted replaced
763:53167294d870 764:f36a6f7e7bdf
738 738
739 739
740 class OrthancMultiframeVolumeLoader : public IObserver 740 class OrthancMultiframeVolumeLoader : public IObserver
741 { 741 {
742 private: 742 private:
743 class Handler : public Orthanc::IDynamicObject 743 class State : public Orthanc::IDynamicObject
744 { 744 {
745 private: 745 private:
746 OrthancMultiframeVolumeLoader& that_; 746 OrthancMultiframeVolumeLoader& that_;
747 std::string instanceId_;
748 747
749 protected: 748 protected:
750 void Schedule(OrthancRestApiCommand* command) const 749 void Schedule(OrthancRestApiCommand* command) const
751 { 750 {
752 that_.oracle_.Schedule(that_, command); 751 that_.oracle_.Schedule(that_, command);
753 } 752 }
754 753
755 const std::string& GetInstanceId() const
756 {
757 return instanceId_;
758 }
759
760 OrthancMultiframeVolumeLoader& GetTarget() const 754 OrthancMultiframeVolumeLoader& GetTarget() const
761 { 755 {
762 return that_; 756 return that_;
763 } 757 }
764 758
765 public: 759 public:
766 Handler(OrthancMultiframeVolumeLoader& that, 760 State(OrthancMultiframeVolumeLoader& that) :
767 const std::string& instanceId) : 761 that_(that)
768 that_(that),
769 instanceId_(instanceId)
770 {
771 }
772
773 Handler(const Handler& previous) :
774 that_(previous.that_),
775 instanceId_(previous.instanceId_)
776 { 762 {
777 } 763 }
778 764
779 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const = 0; 765 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const = 0;
780 }; 766 };
781 767
782 void Handle(const OrthancRestApiCommand::SuccessMessage& message) 768 void Handle(const OrthancRestApiCommand::SuccessMessage& message)
783 { 769 {
784 dynamic_cast<const Handler&>(message.GetOrigin().GetPayload()).Handle(message); 770 dynamic_cast<const State&>(message.GetOrigin().GetPayload()).Handle(message);
785 } 771 }
786 772
787 773
788 class LoadRTDoseGeometry : public Handler 774 class LoadRTDoseGeometry : public State
789 { 775 {
790 private: 776 private:
791 std::auto_ptr<Orthanc::DicomMap> dicom_; 777 std::auto_ptr<Orthanc::DicomMap> dicom_;
792 778
793 public: 779 public:
794 LoadRTDoseGeometry(const Handler& previous, 780 LoadRTDoseGeometry(OrthancMultiframeVolumeLoader& that,
795 Orthanc::DicomMap* dicom) : 781 Orthanc::DicomMap* dicom) :
796 Handler(previous), 782 State(that),
797 dicom_(dicom) 783 dicom_(dicom)
798 { 784 {
799 if (dicom == NULL) 785 if (dicom == NULL)
800 { 786 {
801 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 787 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
809 dicom_->SetValue(Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, s, false); 795 dicom_->SetValue(Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, s, false);
810 796
811 GetTarget().SetGeometry(*dicom_); 797 GetTarget().SetGeometry(*dicom_);
812 } 798 }
813 }; 799 };
800
801
802 static std::string GetSopClassUid(const Orthanc::DicomMap& dicom)
803 {
804 std::string s;
805 if (!dicom.CopyToString(s, Orthanc::DICOM_TAG_SOP_CLASS_UID, false))
806 {
807 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
808 "DICOM file without SOP class UID");
809 }
810 else
811 {
812 return s;
813 }
814 }
814 815
815 816
816 class LoadGeometry : public Handler 817 class LoadGeometry : public State
817 { 818 {
818 public: 819 public:
819 LoadGeometry(OrthancMultiframeVolumeLoader& that, 820 LoadGeometry(OrthancMultiframeVolumeLoader& that) :
820 const std::string& instanceId) : 821 State(that)
821 Handler(that, instanceId)
822 { 822 {
823 } 823 }
824 824
825 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const 825 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const
826 { 826 {
833 } 833 }
834 834
835 std::auto_ptr<Orthanc::DicomMap> dicom(new Orthanc::DicomMap); 835 std::auto_ptr<Orthanc::DicomMap> dicom(new Orthanc::DicomMap);
836 dicom->FromDicomAsJson(body); 836 dicom->FromDicomAsJson(body);
837 837
838 std::string s; 838 if (StringToSopClassUid(GetSopClassUid(*dicom)) == SopClassUid_RTDose)
839 if (!dicom->CopyToString(s, Orthanc::DICOM_TAG_SOP_CLASS_UID, false))
840 {
841 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
842 "DICOM file without SOP class UID");
843 }
844
845 if (StringToSopClassUid(s) == SopClassUid_RTDose)
846 { 839 {
847 // Download the "Grid Frame Offset Vector" DICOM tag, that is 840 // Download the "Grid Frame Offset Vector" DICOM tag, that is
848 // mandatory for RT-DOSE, but is too long to be returned by default 841 // mandatory for RT-DOSE, but is too long to be returned by default
849 842
850 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); 843 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
851 command->SetUri("/instances/" + GetInstanceId() + "/content/" + 844 command->SetUri("/instances/" + GetTarget().GetInstanceId() + "/content/" +
852 Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR.Format()); 845 Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR.Format());
853 command->SetPayload(new LoadRTDoseGeometry(*this, dicom.release())); 846 command->SetPayload(new LoadRTDoseGeometry(GetTarget(), dicom.release()));
854 847
855 Schedule(command.release()); 848 Schedule(command.release());
856 } 849 }
857 else 850 else
858 { 851 {
859 GetTarget().SetGeometry(*dicom); 852 GetTarget().SetGeometry(*dicom);
860 } 853 }
854 }
855 };
856
857
858
859 class LoadTransferSyntax : public State
860 {
861 public:
862 LoadTransferSyntax(OrthancMultiframeVolumeLoader& that) :
863 State(that)
864 {
865 }
866
867 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const
868 {
869 GetTarget().SetTransferSyntax(message.GetAnswer());
861 } 870 }
862 }; 871 };
863 872
864 873
865 874
866 IOracle& oracle_; 875 IOracle& oracle_;
867 bool active_; 876 bool active_;
868 877 std::string instanceId_;
869 std::auto_ptr<ImageBuffer3D> image_; 878 std::string transferSyntaxUid_;
879
870 std::auto_ptr<DicomInstanceParameters> dicom_; 880 std::auto_ptr<DicomInstanceParameters> dicom_;
871 std::auto_ptr<VolumeImageGeometry> geometry_; 881 std::auto_ptr<VolumeImageGeometry> geometry_;
872 882 std::auto_ptr<ImageBuffer3D> image_;
883
884
885 const std::string& GetInstanceId() const
886 {
887 if (active_)
888 {
889 return instanceId_;
890 }
891 else
892 {
893 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
894 }
895 }
896
897
898 void ScheduleFrameDownloads()
899 {
900 if (transferSyntaxUid_.empty() ||
901 !HasGeometry())
902 {
903 return;
904 }
905
906 if (transferSyntaxUid_ != "1.2.840.10008.1.2" &&
907 transferSyntaxUid_ != "1.2.840.10008.1.2.1" &&
908 transferSyntaxUid_ != "1.2.840.10008.1.2.2")
909 {
910 throw Orthanc::OrthancException(
911 Orthanc::ErrorCode_NotImplemented,
912 "No support for multiframe instances with transfer syntax: " + transferSyntaxUid_);
913 }
914 }
915
916
917 void SetTransferSyntax(const std::string& transferSyntax)
918 {
919 transferSyntaxUid_ = Orthanc::Toolbox::StripSpaces(transferSyntax);
920 ScheduleFrameDownloads();
921 }
922
873 923
874 void SetGeometry(const Orthanc::DicomMap& dicom) 924 void SetGeometry(const Orthanc::DicomMap& dicom)
875 { 925 {
876 dicom_.reset(new DicomInstanceParameters(dicom)); 926 dicom_.reset(new DicomInstanceParameters(dicom));
877 927
878 Orthanc::PixelFormat format; 928 Orthanc::PixelFormat format;
879 if (!dicom_->GetImageInformation().ExtractPixelFormat(format, true)) 929 if (!dicom_->GetImageInformation().ExtractPixelFormat(format, true))
880 { 930 {
881 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 931 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
932 }
933
934 double spacingZ;
935 switch (dicom_->GetSopClassUid())
936 {
937 case SopClassUid_RTDose:
938 spacingZ = dicom_->GetThickness();
939 break;
940
941 default:
942 throw Orthanc::OrthancException(
943 Orthanc::ErrorCode_NotImplemented,
944 "No support for multiframe instances with SOP class UID: " + GetSopClassUid(dicom));
882 } 945 }
883 946
884 const unsigned int width = dicom_->GetImageInformation().GetWidth(); 947 const unsigned int width = dicom_->GetImageInformation().GetWidth();
885 const unsigned int height = dicom_->GetImageInformation().GetHeight(); 948 const unsigned int height = dicom_->GetImageInformation().GetHeight();
886 const unsigned int depth = dicom_->GetImageInformation().GetNumberOfFrames(); 949 const unsigned int depth = dicom_->GetImageInformation().GetNumberOfFrames();
888 geometry_.reset(new VolumeImageGeometry); 951 geometry_.reset(new VolumeImageGeometry);
889 geometry_->SetSize(width, height, depth); 952 geometry_->SetSize(width, height, depth);
890 geometry_->SetAxialGeometry(dicom_->GetGeometry()); 953 geometry_->SetAxialGeometry(dicom_->GetGeometry());
891 geometry_->SetVoxelDimensions(dicom_->GetPixelSpacingX(), 954 geometry_->SetVoxelDimensions(dicom_->GetPixelSpacingX(),
892 dicom_->GetPixelSpacingY(), 955 dicom_->GetPixelSpacingY(),
893 dicom_->GetThickness()); 956 spacingZ);
894 957
895 image_.reset(new ImageBuffer3D(format, width, height, depth, 958 image_.reset(new ImageBuffer3D(format, width, height, depth,
896 false /* don't compute range */)); 959 false /* don't compute range */));
897 960
898 { 961 ScheduleFrameDownloads();
899 Orthanc::DicomArray a(dicom);
900 a.Print(stdout);
901 }
902 } 962 }
903 963
904 964
905 public: 965 public:
906 OrthancMultiframeVolumeLoader(IOracle& oracle, 966 OrthancMultiframeVolumeLoader(IOracle& oracle,
912 oracleObservable.RegisterObserverCallback( 972 oracleObservable.RegisterObserverCallback(
913 new Callable<OrthancMultiframeVolumeLoader, OrthancRestApiCommand::SuccessMessage> 973 new Callable<OrthancMultiframeVolumeLoader, OrthancRestApiCommand::SuccessMessage>
914 (*this, &OrthancMultiframeVolumeLoader::Handle)); 974 (*this, &OrthancMultiframeVolumeLoader::Handle));
915 } 975 }
916 976
977
978 bool HasGeometry() const
979 {
980 return (dicom_.get() != NULL &&
981 geometry_.get() != NULL &&
982 image_.get() != NULL);
983 }
984
985
917 void LoadInstance(const std::string& instanceId) 986 void LoadInstance(const std::string& instanceId)
918 { 987 {
919 if (active_) 988 if (active_)
920 { 989 {
921 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 990 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
922 } 991 }
923 else 992 else
924 { 993 {
925 active_ = true; 994 active_ = true;
926 995 instanceId_ = instanceId;
927 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); 996
928 command->SetUri("/instances/" + instanceId + "/tags"); 997 {
929 command->SetPayload(new LoadGeometry(*this, instanceId)); 998 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
930 999 command->SetUri("/instances/" + instanceId + "/tags");
931 oracle_.Schedule(*this, command.release()); 1000 command->SetPayload(new LoadGeometry(*this));
1001 oracle_.Schedule(*this, command.release());
1002 }
1003
1004 {
1005 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
1006 command->SetUri("/instances/" + instanceId + "/metadata/TransferSyntax");
1007 command->SetPayload(new LoadTransferSyntax(*this));
1008 oracle_.Schedule(*this, command.release());
1009 }
932 } 1010 }
933 } 1011 }
934 }; 1012 };
935 1013
936 1014
1321 1399
1322 // 2017-11-17-Anonymized 1400 // 2017-11-17-Anonymized
1323 //loader1->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT 1401 //loader1->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT
1324 loader3->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE 1402 loader3->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE
1325 1403
1404 // 2015-01-28-Multiframe
1405 //loader3->LoadInstance("88f71e2a-5fad1c61-96ed14d6-5b3d3cf7-a5825279"); // Multiframe CT
1406
1326 // Delphine 1407 // Delphine
1327 //loader1->LoadSeries("5990e39c-51e5f201-fe87a54c-31a55943-e59ef80e"); // CT 1408 //loader1->LoadSeries("5990e39c-51e5f201-fe87a54c-31a55943-e59ef80e"); // CT
1328 //loader1->LoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); // Lung 1/10mm 1409 //loader1->LoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); // Lung 1/10mm
1329 1410
1330 1411