comparison Samples/Sdl/Loader.cpp @ 796:d3197e0e321d

DicomStructureSetLoader is working
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 28 May 2019 14:09:46 +0200
parents bc20e4c417ec
children f38c1fc08655
comparison
equal deleted inserted replaced
795:bc20e4c417ec 796:d3197e0e321d
490 490
491 491
492 492
493 493
494 494
495 // TODO - Refactor using LoaderStateMachine?
495 class OrthancSeriesVolumeProgressiveLoader : 496 class OrthancSeriesVolumeProgressiveLoader :
496 public IObserver, 497 public IObserver,
497 public IObservable, 498 public IObservable,
498 public IVolumeSlicer 499 public IVolumeSlicer
499 { 500 {
1003 T& GetLoader() const 1004 T& GetLoader() const
1004 { 1005 {
1005 return dynamic_cast<T&>(that_); 1006 return dynamic_cast<T&>(that_);
1006 } 1007 }
1007 1008
1008 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const 1009 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1009 { 1010 {
1010 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1011 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1011 } 1012 }
1012 1013
1013 virtual void Handle(const GetOrthancImageCommand::SuccessMessage& message) const 1014 virtual void Handle(const GetOrthancImageCommand::SuccessMessage& message)
1014 { 1015 {
1015 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1016 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1016 } 1017 }
1017 1018
1018 virtual void Handle(const GetOrthancWebViewerJpegCommand::SuccessMessage& message) const 1019 virtual void Handle(const GetOrthancWebViewerJpegCommand::SuccessMessage& message)
1019 { 1020 {
1020 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); 1021 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1021 } 1022 }
1022 }; 1023 };
1023 1024
1073 for (PendingCommands::iterator it = pendingCommands_.begin(); 1074 for (PendingCommands::iterator it = pendingCommands_.begin();
1074 it != pendingCommands_.end(); ++it) 1075 it != pendingCommands_.end(); ++it)
1075 { 1076 {
1076 delete *it; 1077 delete *it;
1077 } 1078 }
1078 } 1079
1079 1080 pendingCommands_.clear();
1080 void HandleException(const OracleCommandExceptionMessage& message) 1081 }
1082
1083 void HandleExceptionMessage(const OracleCommandExceptionMessage& message)
1081 { 1084 {
1082 LOG(ERROR) << "Error in the state machine, stopping all processing"; 1085 LOG(ERROR) << "Error in the state machine, stopping all processing";
1083 Clear(); 1086 Clear();
1084 } 1087 }
1085 1088
1086 template <typename T> 1089 template <typename T>
1087 void Handle(const T& message) 1090 void HandleSuccessMessage(const T& message)
1088 { 1091 {
1089 dynamic_cast<const State&>(message.GetOrigin().GetPayload()).Handle(message); 1092 assert(activeCommands_ > 0);
1090 activeCommands_--; 1093 activeCommands_--;
1091 Step(); 1094
1095 try
1096 {
1097 dynamic_cast<State&>(message.GetOrigin().GetPayload()).Handle(message);
1098 Step();
1099 }
1100 catch (Orthanc::OrthancException& e)
1101 {
1102 LOG(ERROR) << "Error in the state machine, stopping all processing: " << e.What();
1103 Clear();
1104 }
1092 } 1105 }
1093 1106
1094 typedef std::list<IOracleCommand*> PendingCommands; 1107 typedef std::list<IOracleCommand*> PendingCommands;
1095 1108
1096 IOracle& oracle_; 1109 IOracle& oracle_;
1108 simultaneousDownloads_(4), 1121 simultaneousDownloads_(4),
1109 activeCommands_(0) 1122 activeCommands_(0)
1110 { 1123 {
1111 oracleObservable.RegisterObserverCallback( 1124 oracleObservable.RegisterObserverCallback(
1112 new Callable<LoaderStateMachine, OrthancRestApiCommand::SuccessMessage> 1125 new Callable<LoaderStateMachine, OrthancRestApiCommand::SuccessMessage>
1113 (*this, &LoaderStateMachine::Handle<OrthancRestApiCommand::SuccessMessage>)); 1126 (*this, &LoaderStateMachine::HandleSuccessMessage));
1114 1127
1115 oracleObservable.RegisterObserverCallback( 1128 oracleObservable.RegisterObserverCallback(
1116 new Callable<LoaderStateMachine, GetOrthancImageCommand::SuccessMessage> 1129 new Callable<LoaderStateMachine, GetOrthancImageCommand::SuccessMessage>
1117 (*this, &LoaderStateMachine::Handle<GetOrthancImageCommand::SuccessMessage>)); 1130 (*this, &LoaderStateMachine::HandleSuccessMessage));
1118 1131
1119 oracleObservable.RegisterObserverCallback( 1132 oracleObservable.RegisterObserverCallback(
1120 new Callable<LoaderStateMachine, GetOrthancWebViewerJpegCommand::SuccessMessage> 1133 new Callable<LoaderStateMachine, GetOrthancWebViewerJpegCommand::SuccessMessage>
1121 (*this, &LoaderStateMachine::Handle<GetOrthancWebViewerJpegCommand::SuccessMessage>)); 1134 (*this, &LoaderStateMachine::HandleSuccessMessage));
1122 1135
1123 oracleObservable.RegisterObserverCallback( 1136 oracleObservable.RegisterObserverCallback(
1124 new Callable<LoaderStateMachine, OracleCommandExceptionMessage> 1137 new Callable<LoaderStateMachine, OracleCommandExceptionMessage>
1125 (*this, &LoaderStateMachine::HandleException)); 1138 (*this, &LoaderStateMachine::HandleExceptionMessage));
1126 } 1139 }
1127 1140
1128 virtual ~LoaderStateMachine() 1141 virtual ~LoaderStateMachine()
1129 { 1142 {
1130 Clear(); 1143 Clear();
1175 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 1188 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
1176 } 1189 }
1177 1190
1178 } 1191 }
1179 1192
1180 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const 1193 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1181 { 1194 {
1182 // Complete the DICOM tags with just-received "Grid Frame Offset Vector" 1195 // Complete the DICOM tags with just-received "Grid Frame Offset Vector"
1183 std::string s = Orthanc::Toolbox::StripSpaces(message.GetAnswer()); 1196 std::string s = Orthanc::Toolbox::StripSpaces(message.GetAnswer());
1184 dicom_->SetValue(Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, s, false); 1197 dicom_->SetValue(Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, s, false);
1185 1198
1209 LoadGeometry(OrthancMultiframeVolumeLoader& that) : 1222 LoadGeometry(OrthancMultiframeVolumeLoader& that) :
1210 State(that) 1223 State(that)
1211 { 1224 {
1212 } 1225 }
1213 1226
1214 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const 1227 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1215 { 1228 {
1216 OrthancMultiframeVolumeLoader& loader = GetLoader<OrthancMultiframeVolumeLoader>(); 1229 OrthancMultiframeVolumeLoader& loader = GetLoader<OrthancMultiframeVolumeLoader>();
1217 1230
1218 Json::Value body; 1231 Json::Value body;
1219 message.ParseJsonBody(body); 1232 message.ParseJsonBody(body);
1253 LoadTransferSyntax(OrthancMultiframeVolumeLoader& that) : 1266 LoadTransferSyntax(OrthancMultiframeVolumeLoader& that) :
1254 State(that) 1267 State(that)
1255 { 1268 {
1256 } 1269 }
1257 1270
1258 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const 1271 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1259 { 1272 {
1260 GetLoader<OrthancMultiframeVolumeLoader>().SetTransferSyntax(message.GetAnswer()); 1273 GetLoader<OrthancMultiframeVolumeLoader>().SetTransferSyntax(message.GetAnswer());
1261 } 1274 }
1262 }; 1275 };
1263 1276
1268 LoadUncompressedPixelData(OrthancMultiframeVolumeLoader& that) : 1281 LoadUncompressedPixelData(OrthancMultiframeVolumeLoader& that) :
1269 State(that) 1282 State(that)
1270 { 1283 {
1271 } 1284 }
1272 1285
1273 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const 1286 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1274 { 1287 {
1275 GetLoader<OrthancMultiframeVolumeLoader>().SetUncompressedPixelData(message.GetAnswer()); 1288 GetLoader<OrthancMultiframeVolumeLoader>().SetUncompressedPixelData(message.GetAnswer());
1276 } 1289 }
1277 }; 1290 };
1278 1291
1489 } 1502 }
1490 }; 1503 };
1491 1504
1492 1505
1493 1506
1494 class VolumeImageReslicer : public IVolumeSlicer 1507 class DicomVolumeImageReslicer : public IVolumeSlicer
1495 { 1508 {
1496 private: 1509 private:
1497 class Slice : public IExtractedSlice 1510 class Slice : public IExtractedSlice
1498 { 1511 {
1499 private: 1512 private:
1500 VolumeImageReslicer& that_; 1513 DicomVolumeImageReslicer& that_;
1501 CoordinateSystem3D cuttingPlane_; 1514 CoordinateSystem3D cuttingPlane_;
1502 1515
1503 public: 1516 public:
1504 Slice(VolumeImageReslicer& that, 1517 Slice(DicomVolumeImageReslicer& that,
1505 const CoordinateSystem3D& cuttingPlane) : 1518 const CoordinateSystem3D& cuttingPlane) :
1506 that_(that), 1519 that_(that),
1507 cuttingPlane_(cuttingPlane) 1520 cuttingPlane_(cuttingPlane)
1508 { 1521 {
1509 } 1522 }
1516 virtual uint64_t GetRevision() 1529 virtual uint64_t GetRevision()
1517 { 1530 {
1518 return that_.volume_->GetRevision(); 1531 return that_.volume_->GetRevision();
1519 } 1532 }
1520 1533
1521 virtual ISceneLayer* CreateSceneLayer(const ILayerStyleConfigurator* configurator, // possibly absent 1534 virtual ISceneLayer* CreateSceneLayer(const ILayerStyleConfigurator* configurator,
1522 const CoordinateSystem3D& cuttingPlane) 1535 const CoordinateSystem3D& cuttingPlane)
1523 { 1536 {
1524 VolumeReslicer& reslicer = that_.reslicer_; 1537 VolumeReslicer& reslicer = that_.reslicer_;
1525 1538
1526 if (configurator == NULL) 1539 if (configurator == NULL)
1562 1575
1563 boost::shared_ptr<DicomVolumeImage> volume_; 1576 boost::shared_ptr<DicomVolumeImage> volume_;
1564 VolumeReslicer reslicer_; 1577 VolumeReslicer reslicer_;
1565 1578
1566 public: 1579 public:
1567 VolumeImageReslicer(const boost::shared_ptr<DicomVolumeImage>& volume) : 1580 DicomVolumeImageReslicer(const boost::shared_ptr<DicomVolumeImage>& volume) :
1568 volume_(volume) 1581 volume_(volume)
1569 { 1582 {
1570 if (volume.get() == NULL) 1583 if (volume.get() == NULL)
1571 { 1584 {
1572 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 1585 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
1607 }; 1620 };
1608 1621
1609 1622
1610 1623
1611 class DicomStructureSetLoader : 1624 class DicomStructureSetLoader :
1612 public IObserver, 1625 public LoaderStateMachine,
1613 public IVolumeSlicer 1626 public IVolumeSlicer
1614 { 1627 {
1615 private: 1628 private:
1629 class AddReferencedInstance : public State
1630 {
1631 private:
1632 std::string instanceId_;
1633
1634 public:
1635 AddReferencedInstance(DicomStructureSetLoader& that,
1636 const std::string& instanceId) :
1637 State(that),
1638 instanceId_(instanceId)
1639 {
1640 }
1641
1642 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1643 {
1644 Json::Value tags;
1645 message.ParseJsonBody(tags);
1646
1647 Orthanc::DicomMap dicom;
1648 dicom.FromDicomAsJson(tags);
1649
1650 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>();
1651 loader.content_->AddReferencedSlice(dicom);
1652
1653 loader.countProcessedInstances_ ++;
1654 assert(loader.countProcessedInstances_ <= loader.countReferencedInstances_);
1655
1656 if (loader.countProcessedInstances_ == loader.countReferencedInstances_)
1657 {
1658 // All the referenced instances have been loaded, finalize the RT-STRUCT
1659 loader.content_->CheckReferencedSlices();
1660 loader.revision_++;
1661 }
1662 }
1663 };
1664
1665 // State that converts a "SOP Instance UID" to an Orthanc identifier
1666 class LookupInstance : public State
1667 {
1668 private:
1669 std::string sopInstanceUid_;
1670
1671 public:
1672 LookupInstance(DicomStructureSetLoader& that,
1673 const std::string& sopInstanceUid) :
1674 State(that),
1675 sopInstanceUid_(sopInstanceUid)
1676 {
1677 }
1678
1679 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1680 {
1681 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>();
1682
1683 Json::Value lookup;
1684 message.ParseJsonBody(lookup);
1685
1686 if (lookup.type() != Json::arrayValue ||
1687 lookup.size() != 1 ||
1688 !lookup[0].isMember("Type") ||
1689 !lookup[0].isMember("Path") ||
1690 lookup[0]["Type"].type() != Json::stringValue ||
1691 lookup[0]["ID"].type() != Json::stringValue ||
1692 lookup[0]["Type"].asString() != "Instance")
1693 {
1694 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
1695 }
1696
1697 const std::string instanceId = lookup[0]["ID"].asString();
1698
1699 {
1700 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
1701 command->SetHttpHeader("Accept-Encoding", "gzip");
1702 command->SetUri("/instances/" + instanceId + "/tags");
1703 command->SetPayload(new AddReferencedInstance(loader, instanceId));
1704 Schedule(command.release());
1705 }
1706 }
1707 };
1708
1709 class LoadStructure : public State
1710 {
1711 public:
1712 LoadStructure(DicomStructureSetLoader& that) :
1713 State(that)
1714 {
1715 }
1716
1717 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message)
1718 {
1719 DicomStructureSetLoader& loader = GetLoader<DicomStructureSetLoader>();
1720
1721 {
1722 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer());
1723 loader.content_.reset(new DicomStructureSet(dicom));
1724 }
1725
1726 std::set<std::string> instances;
1727 loader.content_->GetReferencedInstances(instances);
1728
1729 loader.countReferencedInstances_ = instances.size();
1730
1731 for (std::set<std::string>::const_iterator
1732 it = instances.begin(); it != instances.end(); ++it)
1733 {
1734 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
1735 command->SetUri("/tools/lookup");
1736 command->SetMethod(Orthanc::HttpMethod_Post);
1737 command->SetBody(*it);
1738 command->SetPayload(new LookupInstance(loader, *it));
1739 Schedule(command.release());
1740
1741 printf("[%s]\n", it->c_str());
1742 }
1743 }
1744 };
1745
1746
1747
1616 std::auto_ptr<DicomStructureSet> content_; 1748 std::auto_ptr<DicomStructureSet> content_;
1617 IOracle& oracle_;
1618 bool active_;
1619 uint64_t revision_; 1749 uint64_t revision_;
1620 std::string instanceId_; 1750 std::string instanceId_;
1621 1751 unsigned int countProcessedInstances_;
1622 void Handle(const OrthancRestApiCommand::SuccessMessage& message) 1752 unsigned int countReferencedInstances_;
1623 {
1624 assert(active_);
1625
1626 {
1627 OrthancPlugins::FullOrthancDataset dicom(message.GetAnswer());
1628 content_.reset(new DicomStructureSet(dicom));
1629 }
1630
1631 std::set<std::string> instances;
1632 content_->GetReferencedInstances(instances);
1633
1634 for (std::set<std::string>::const_iterator
1635 it = instances.begin(); it != instances.end(); ++it)
1636 {
1637 printf("[%s]\n", it->c_str());
1638 }
1639 }
1640 1753
1641 1754
1642 class Slice : public IExtractedSlice 1755 class Slice : public IExtractedSlice
1643 { 1756 {
1644 private: 1757 private:
1676 const CoordinateSystem3D& cuttingPlane) 1789 const CoordinateSystem3D& cuttingPlane)
1677 { 1790 {
1678 assert(isValid_); 1791 assert(isValid_);
1679 1792
1680 std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer); 1793 std::auto_ptr<PolylineSceneLayer> layer(new PolylineSceneLayer);
1794 layer->SetThickness(2);
1681 1795
1682 for (size_t i = 0; i < content_.GetStructuresCount(); i++) 1796 for (size_t i = 0; i < content_.GetStructuresCount(); i++)
1683 { 1797 {
1684 std::vector< std::vector<DicomStructureSet::PolygonPoint> > polygons; 1798 std::vector< std::vector<DicomStructureSet::PolygonPoint> > polygons;
1685 1799
1686 if (content_.ProjectStructure(polygons, i, cuttingPlane)) 1800 if (content_.ProjectStructure(polygons, i, cuttingPlane))
1687 { 1801 {
1688 printf(">> %d\n", polygons.size());
1689
1690 for (size_t j = 0; j < polygons.size(); j++) 1802 for (size_t j = 0; j < polygons.size(); j++)
1691 { 1803 {
1692 PolylineSceneLayer::Chain chain; 1804 PolylineSceneLayer::Chain chain;
1693 chain.resize(polygons[j].size()); 1805 chain.resize(polygons[j].size());
1694 1806
1695 for (size_t k = 0; k < polygons[i].size(); k++) 1807 for (size_t k = 0; k < polygons[j].size(); k++)
1696 { 1808 {
1697 chain[k] = ScenePoint2D(polygons[j][k].first, polygons[j][k].second); 1809 chain[k] = ScenePoint2D(polygons[j][k].first, polygons[j][k].second);
1698 } 1810 }
1699 1811
1700 layer->AddChain(chain, true /* closed */); 1812 layer->AddChain(chain, true /* closed */);
1701 } 1813 }
1702 } 1814 }
1703 } 1815 }
1704 1816
1705 printf("OK\n");
1706
1707 return layer.release(); 1817 return layer.release();
1708 } 1818 }
1709 }; 1819 };
1710 1820
1711 public: 1821 public:
1712 DicomStructureSetLoader(IOracle& oracle, 1822 DicomStructureSetLoader(IOracle& oracle,
1713 IObservable& oracleObservable) : 1823 IObservable& oracleObservable) :
1714 IObserver(oracleObservable.GetBroker()), 1824 LoaderStateMachine(oracle, oracleObservable),
1715 oracle_(oracle), 1825 revision_(0),
1716 active_(false), 1826 countProcessedInstances_(0),
1717 revision_(0) 1827 countReferencedInstances_(0)
1718 { 1828 {
1719 oracleObservable.RegisterObserverCallback(
1720 new Callable<DicomStructureSetLoader, OrthancRestApiCommand::SuccessMessage>
1721 (*this, &DicomStructureSetLoader::Handle));
1722 } 1829 }
1723 1830
1724 1831
1725 void LoadInstance(const std::string& instanceId) 1832 void LoadInstance(const std::string& instanceId)
1726 { 1833 {
1727 if (active_) 1834 Start();
1728 { 1835
1729 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 1836 instanceId_ = instanceId;
1730 } 1837
1731 else 1838 {
1732 { 1839 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
1733 active_ = true; 1840 command->SetHttpHeader("Accept-Encoding", "gzip");
1734 instanceId_ = instanceId; 1841 command->SetUri("/instances/" + instanceId + "/tags?ignore-length=3006-0050");
1735 1842 command->SetPayload(new LoadStructure(*this));
1736 { 1843 Schedule(command.release());
1737 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
1738 command->SetHttpHeader("Accept-Encoding", "gzip");
1739 command->SetUri("/instances/" + instanceId + "/tags?ignore-length=3006-0050");
1740 oracle_.Schedule(*this, command.release());
1741 }
1742 } 1844 }
1743 } 1845 }
1744 1846
1745 virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane) 1847 virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane)
1746 { 1848 {
2179 2281
2180 #if 1 2282 #if 1
2181 toto->SetVolume1(0, ctLoader, new OrthancStone::GrayscaleStyleConfigurator); 2283 toto->SetVolume1(0, ctLoader, new OrthancStone::GrayscaleStyleConfigurator);
2182 #else 2284 #else
2183 { 2285 {
2184 boost::shared_ptr<OrthancStone::IVolumeSlicer> reslicer(new OrthancStone::VolumeImageReslicer(ct)); 2286 boost::shared_ptr<OrthancStone::IVolumeSlicer> reslicer(new OrthancStone::DicomVolumeImageReslicer(ct));
2185 toto->SetVolume1(0, reslicer, new OrthancStone::GrayscaleStyleConfigurator); 2287 toto->SetVolume1(0, reslicer, new OrthancStone::GrayscaleStyleConfigurator);
2186 } 2288 }
2187 #endif 2289 #endif
2188 2290
2189 2291
2275 } 2377 }
2276 2378
2277 2379
2278 // 2017-11-17-Anonymized 2380 // 2017-11-17-Anonymized
2279 //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT 2381 //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT
2280 doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE 2382 //doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE
2281 //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT 2383 //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT
2384
2385 // 2017-05-16
2386 ctLoader->LoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // CT
2387 doseLoader->LoadInstance("eac822ef-a395f94e-e8121fe0-8411fef8-1f7bffad"); // RT-DOSE
2388 rtstructLoader->LoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // RT-STRUCT
2282 2389
2283 // 2015-01-28-Multiframe 2390 // 2015-01-28-Multiframe
2284 //doseLoader->LoadInstance("88f71e2a-5fad1c61-96ed14d6-5b3d3cf7-a5825279"); // Multiframe CT 2391 //doseLoader->LoadInstance("88f71e2a-5fad1c61-96ed14d6-5b3d3cf7-a5825279"); // Multiframe CT
2285 2392
2286 // Delphine 2393 // Delphine