# HG changeset patch # User Benjamin Golinvaux # Date 1559024138 -7200 # Node ID c83a45f864b2fe8af63b4fe5859e94d783724d74 # Parent e76c4eef1054a3dc27dc16e44167bc7661dd3ced# Parent 5aa7285005868638bc58b6b63a1b4b837c92a5a5 Merge diff -r e76c4eef1054 -r c83a45f864b2 Framework/Toolbox/DicomStructureSet.cpp --- a/Framework/Toolbox/DicomStructureSet.cpp Mon May 27 16:01:47 2019 +0200 +++ b/Framework/Toolbox/DicomStructureSet.cpp Tue May 28 08:15:38 2019 +0200 @@ -422,24 +422,43 @@ << static_cast(structures_[i].green_) << "," << static_cast(structures_[i].blue_) << ")"; + + // These temporary variables avoid allocating many vectors in the loop below + OrthancPlugins::DicomPath countPointsPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, + DICOM_TAG_CONTOUR_SEQUENCE, 0, + DICOM_TAG_NUMBER_OF_CONTOUR_POINTS); + + OrthancPlugins::DicomPath geometricTypePath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, + DICOM_TAG_CONTOUR_SEQUENCE, 0, + DICOM_TAG_CONTOUR_GEOMETRIC_TYPE); + + OrthancPlugins::DicomPath imageSequencePath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, + DICOM_TAG_CONTOUR_SEQUENCE, 0, + DICOM_TAG_CONTOUR_IMAGE_SEQUENCE); + + OrthancPlugins::DicomPath referencedInstancePath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, + DICOM_TAG_CONTOUR_SEQUENCE, 0, + DICOM_TAG_CONTOUR_IMAGE_SEQUENCE, 0, + DICOM_TAG_REFERENCED_SOP_INSTANCE_UID); + + OrthancPlugins::DicomPath contourDataPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, + DICOM_TAG_CONTOUR_SEQUENCE, 0, + DICOM_TAG_CONTOUR_DATA); + for (size_t j = 0; j < countSlices; j++) { unsigned int countPoints; - if (!reader.GetUnsignedIntegerValue - (countPoints, OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, - DICOM_TAG_CONTOUR_SEQUENCE, j, - DICOM_TAG_NUMBER_OF_CONTOUR_POINTS))) + countPointsPath.SetPrefixIndex(1, j); + if (!reader.GetUnsignedIntegerValue(countPoints, countPointsPath)) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); } //LOG(INFO) << "Parsing slice containing " << countPoints << " vertices"; - std::string type = reader.GetMandatoryStringValue - (OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, - DICOM_TAG_CONTOUR_SEQUENCE, j, - DICOM_TAG_CONTOUR_GEOMETRIC_TYPE)); + geometricTypePath.SetPrefixIndex(1, j); + std::string type = reader.GetMandatoryStringValue(geometricTypePath); if (type != "CLOSED_PLANAR") { LOG(WARNING) << "Ignoring contour with geometry type: " << type; @@ -447,24 +466,19 @@ } size_t size; - if (!tags.GetSequenceSize(size, OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, - DICOM_TAG_CONTOUR_SEQUENCE, j, - DICOM_TAG_CONTOUR_IMAGE_SEQUENCE)) || + + imageSequencePath.SetPrefixIndex(1, j); + if (!tags.GetSequenceSize(size, imageSequencePath) || size != 1) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } - std::string sopInstanceUid = reader.GetMandatoryStringValue - (OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, - DICOM_TAG_CONTOUR_SEQUENCE, j, - DICOM_TAG_CONTOUR_IMAGE_SEQUENCE, 0, - DICOM_TAG_REFERENCED_SOP_INSTANCE_UID)); - - std::string slicesData = reader.GetMandatoryStringValue - (OrthancPlugins::DicomPath(DICOM_TAG_ROI_CONTOUR_SEQUENCE, i, - DICOM_TAG_CONTOUR_SEQUENCE, j, - DICOM_TAG_CONTOUR_DATA)); + referencedInstancePath.SetPrefixIndex(1, j); + std::string sopInstanceUid = reader.GetMandatoryStringValue(referencedInstancePath); + + contourDataPath.SetPrefixIndex(1, j); + std::string slicesData = reader.GetMandatoryStringValue(contourDataPath); Vector points; if (!LinearAlgebra::ParseVector(points, slicesData) || diff -r e76c4eef1054 -r c83a45f864b2 Framework/Toolbox/DicomStructureSet.h --- a/Framework/Toolbox/DicomStructureSet.h Mon May 27 16:01:47 2019 +0200 +++ b/Framework/Toolbox/DicomStructureSet.h Tue May 28 08:15:38 2019 +0200 @@ -170,6 +170,7 @@ Vector GetNormal() const; + // TODO - Remove static DicomStructureSet* SynchronousLoad(OrthancPlugins::IOrthancConnection& orthanc, const std::string& instanceId); diff -r e76c4eef1054 -r c83a45f864b2 Framework/Toolbox/LinearAlgebra.cpp --- a/Framework/Toolbox/LinearAlgebra.cpp Mon May 27 16:01:47 2019 +0200 +++ b/Framework/Toolbox/LinearAlgebra.cpp Tue May 28 08:15:38 2019 +0200 @@ -63,7 +63,7 @@ const std::string& value) { std::vector items; - Orthanc::Toolbox::TokenizeString(items, value, '\\'); + Orthanc::Toolbox::TokenizeString(items, Orthanc::Toolbox::StripSpaces(value), '\\'); target.resize(items.size()); @@ -71,7 +71,7 @@ { try { - target[i] = boost::lexical_cast(Orthanc::Toolbox::StripSpaces(items[i])); + target[i] = boost::lexical_cast(items[i]); } catch (boost::bad_lexical_cast&) { diff -r e76c4eef1054 -r c83a45f864b2 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Mon May 27 16:01:47 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Tue May 28 08:15:38 2019 +0200 @@ -313,10 +313,6 @@ if (ENABLE_STONE_DEPRECATED) list(APPEND ORTHANC_STONE_SOURCES - ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomDatasetReader.cpp - ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomPath.cpp - ${ORTHANC_ROOT}/Plugins/Samples/Common/FullOrthancDataset.cpp - ${ORTHANC_ROOT}/Plugins/Samples/Common/IOrthancConnection.cpp ${ORTHANC_STONE_ROOT}/Framework/Deprecated/Layers/CircleMeasureTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Deprecated/Layers/ColorFrameRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Deprecated/Layers/DicomSeriesVolumeSlicer.cpp @@ -373,6 +369,11 @@ #${ORTHANC_STONE_ROOT}/Framework/Layers/SeriesFrameRendererFactory.cpp #${ORTHANC_STONE_ROOT}/Framework/Layers/SingleFrameRendererFactory.cpp + ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomDatasetReader.cpp + ${ORTHANC_ROOT}/Plugins/Samples/Common/DicomPath.cpp + ${ORTHANC_ROOT}/Plugins/Samples/Common/FullOrthancDataset.cpp + ${ORTHANC_ROOT}/Plugins/Samples/Common/IOrthancConnection.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/CairoCompositor.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ColorTextureSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/FloatTextureSceneLayer.cpp diff -r e76c4eef1054 -r c83a45f864b2 Samples/Sdl/Loader.cpp --- a/Samples/Sdl/Loader.cpp Mon May 27 16:01:47 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Tue May 28 08:15:38 2019 +0200 @@ -37,6 +37,7 @@ #include "../../Framework/StoneInitialization.h" #include "../../Framework/Toolbox/GeometryToolbox.h" #include "../../Framework/Toolbox/SlicesSorter.h" +#include "../../Framework/Toolbox/DicomStructureSet.h" #include "../../Framework/Volumes/ImageBuffer3D.h" #include "../../Framework/Volumes/VolumeImageGeometry.h" #include "../../Framework/Volumes/VolumeReslicer.h" @@ -1463,6 +1464,86 @@ + class DicomStructureSetLoader : + public IObserver, + public IVolumeSlicer + { + private: + enum State + { + State_Setup, + State_Loading, + State_Ready + }; + + + std::auto_ptr content_; + IOracle& oracle_; + State state_; + std::string instanceId_; + + void Handle(const OrthancRestApiCommand::SuccessMessage& message) + { + if (state_ != State_Loading) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + + const boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time(); + + { + OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer()); + content_.reset(new DicomStructureSet(dicom)); + } + + const boost::posix_time::ptime end = boost::posix_time::microsec_clock::local_time(); + + printf("LOADED: %d\n", (end - start).total_milliseconds()); + state_ = State_Ready; + } + + + public: + DicomStructureSetLoader(IOracle& oracle, + IObservable& oracleObservable) : + IObserver(oracleObservable.GetBroker()), + oracle_(oracle), + state_(State_Setup) + { + oracleObservable.RegisterObserverCallback( + new Callable + (*this, &DicomStructureSetLoader::Handle)); + } + + + void LoadInstance(const std::string& instanceId) + { + if (state_ != State_Setup) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + state_ = State_Loading; + instanceId_ = instanceId; + + { + std::auto_ptr command(new OrthancRestApiCommand); + command->SetHttpHeader("Accept-Encoding", "gzip"); + command->SetUri("/instances/" + instanceId + "/tags?ignore-length=3006-0050"); + oracle_.Schedule(*this, command.release()); + } + } + } + + virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane) + { + return NULL; + } + }; + + + class VolumeSceneLayerSource : public boost::noncopyable { private: @@ -1855,12 +1936,14 @@ boost::shared_ptr toto; boost::shared_ptr ctLoader; boost::shared_ptr doseLoader; + boost::shared_ptr rtstructLoader; { OrthancStone::NativeApplicationContext::WriterLock lock(context); toto.reset(new Toto(oracle, lock.GetOracleObservable())); ctLoader.reset(new OrthancStone::OrthancSeriesVolumeProgressiveLoader(ct, oracle, lock.GetOracleObservable())); doseLoader.reset(new OrthancStone::OrthancMultiframeVolumeLoader(dose, oracle, lock.GetOracleObservable())); + rtstructLoader.reset(new OrthancStone::DicomStructureSetLoader(oracle, lock.GetOracleObservable())); } @@ -1883,7 +1966,7 @@ toto->SetVolume2(1, doseLoader, config.release()); } - oracle.Schedule(*toto, new OrthancStone::SleepOracleCommand(100)); + //oracle.Schedule(*toto, new OrthancStone::SleepOracleCommand(100)); if (0) { @@ -1960,9 +2043,11 @@ } } + // 2017-11-17-Anonymized - ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT - doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE + //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT + //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE + rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT // 2015-01-28-Multiframe //doseLoader->LoadInstance("88f71e2a-5fad1c61-96ed14d6-5b3d3cf7-a5825279"); // Multiframe CT