Mercurial > hg > orthanc-stone
comparison Framework/SmartLoader.cpp @ 396:ed7146fa2c98
rename ILayerSource as IVolumeSlicer, and OrthancFrameLayerSource as as DicomSeriesVolumeSlicer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sat, 10 Nov 2018 09:29:08 +0100 |
parents | 5f13809f3f76 |
children | f1c769b3a5c2 |
comparison
equal
deleted
inserted
replaced
395:5f13809f3f76 | 396:ed7146fa2c98 |
---|---|
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 **/ | 19 **/ |
20 | 20 |
21 | 21 |
22 #include "SmartLoader.h" | 22 #include "SmartLoader.h" |
23 #include "Layers/OrthancFrameLayerSource.h" | 23 #include "Layers/DicomSeriesVolumeSlicer.h" |
24 #include "Messages/MessageForwarder.h" | 24 #include "Messages/MessageForwarder.h" |
25 #include "Core/Images/Image.h" | 25 #include "Core/Images/Image.h" |
26 #include "Framework/Widgets/SliceViewerWidget.h" | 26 #include "Framework/Widgets/SliceViewerWidget.h" |
27 #include "Framework/StoneException.h" | 27 #include "Framework/StoneException.h" |
28 #include "Framework/Layers/FrameRenderer.h" | 28 #include "Framework/Layers/FrameRenderer.h" |
35 CachedSliceStatus_ScheduledToLoad, | 35 CachedSliceStatus_ScheduledToLoad, |
36 CachedSliceStatus_GeometryLoaded, | 36 CachedSliceStatus_GeometryLoaded, |
37 CachedSliceStatus_ImageLoaded | 37 CachedSliceStatus_ImageLoaded |
38 }; | 38 }; |
39 | 39 |
40 class SmartLoader::CachedSlice : public LayerSourceBase | 40 class SmartLoader::CachedSlice : public VolumeSlicerBase |
41 { | 41 { |
42 public: | 42 public: |
43 class RendererFactory : public LayerReadyMessage::IRendererFactory | 43 class RendererFactory : public LayerReadyMessage::IRendererFactory |
44 { | 44 { |
45 private: | 45 private: |
66 SliceImageQuality effectiveQuality_; | 66 SliceImageQuality effectiveQuality_; |
67 CachedSliceStatus status_; | 67 CachedSliceStatus status_; |
68 | 68 |
69 public: | 69 public: |
70 CachedSlice(MessageBroker& broker) : | 70 CachedSlice(MessageBroker& broker) : |
71 LayerSourceBase(broker) | 71 VolumeSlicerBase(broker) |
72 { | 72 { |
73 } | 73 } |
74 | 74 |
75 virtual ~CachedSlice() | 75 virtual ~CachedSlice() |
76 { | 76 { |
87 virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) | 87 virtual void ScheduleLayerCreation(const CoordinateSystem3D& viewportSlice) |
88 { | 88 { |
89 // TODO: viewportSlice is not used !!!! | 89 // TODO: viewportSlice is not used !!!! |
90 | 90 |
91 // it has already been loaded -> trigger the "layer ready" message immediately otherwise, do nothing now. The LayerReady will be triggered | 91 // it has already been loaded -> trigger the "layer ready" message immediately otherwise, do nothing now. The LayerReady will be triggered |
92 // once the LayerSource is ready | 92 // once the VolumeSlicer is ready |
93 if (status_ == CachedSliceStatus_ImageLoaded) | 93 if (status_ == CachedSliceStatus_ImageLoaded) |
94 { | 94 { |
95 LOG(WARNING) << "ScheduleLayerCreation for CachedSlice (image is loaded): " << slice_->GetOrthancInstanceId(); | 95 LOG(WARNING) << "ScheduleLayerCreation for CachedSlice (image is loaded): " << slice_->GetOrthancInstanceId(); |
96 | 96 |
97 RendererFactory factory(*this); | 97 RendererFactory factory(*this); |
98 LayerSourceBase::NotifyLayerReady(factory, slice_->GetGeometry()); | 98 VolumeSlicerBase::NotifyLayerReady(factory, slice_->GetGeometry()); |
99 } | 99 } |
100 else | 100 else |
101 { | 101 { |
102 LOG(WARNING) << "ScheduleLayerCreation for CachedSlice (image is not loaded yet): " << slice_->GetOrthancInstanceId(); | 102 LOG(WARNING) << "ScheduleLayerCreation for CachedSlice (image is not loaded yet): " << slice_->GetOrthancInstanceId(); |
103 } | 103 } |
133 unsigned int frame) | 133 unsigned int frame) |
134 { | 134 { |
135 // TODO: check if this frame has already been loaded or is already being loaded. | 135 // TODO: check if this frame has already been loaded or is already being loaded. |
136 // - if already loaded: create a "clone" that will emit the GeometryReady/ImageReady messages "immediately" | 136 // - if already loaded: create a "clone" that will emit the GeometryReady/ImageReady messages "immediately" |
137 // (it can not be immediate because Observers needs to register first and this is done after this method returns) | 137 // (it can not be immediate because Observers needs to register first and this is done after this method returns) |
138 // - if currently loading, we need to return an object that will observe the existing LayerSource and forward | 138 // - if currently loading, we need to return an object that will observe the existing VolumeSlicer and forward |
139 // the messages to its observables | 139 // the messages to its observables |
140 // in both cases, we must be carefull about objects lifecycle !!! | 140 // in both cases, we must be carefull about objects lifecycle !!! |
141 | 141 |
142 std::auto_ptr<ILayerSource> layerSource; | 142 std::auto_ptr<IVolumeSlicer> layerSource; |
143 std::string sliceKeyId = instanceId + ":" + boost::lexical_cast<std::string>(frame); | 143 std::string sliceKeyId = instanceId + ":" + boost::lexical_cast<std::string>(frame); |
144 SmartLoader::CachedSlice* cachedSlice = NULL; | 144 SmartLoader::CachedSlice* cachedSlice = NULL; |
145 | 145 |
146 if (cachedSlices_.find(sliceKeyId) != cachedSlices_.end()) // && cachedSlices_[sliceKeyId]->status_ == CachedSliceStatus_Loaded) | 146 if (cachedSlices_.find(sliceKeyId) != cachedSlices_.end()) // && cachedSlices_[sliceKeyId]->status_ == CachedSliceStatus_Loaded) |
147 { | 147 { |
148 layerSource.reset(cachedSlices_[sliceKeyId]->Clone()); | 148 layerSource.reset(cachedSlices_[sliceKeyId]->Clone()); |
149 cachedSlice = dynamic_cast<SmartLoader::CachedSlice*>(layerSource.get()); | 149 cachedSlice = dynamic_cast<SmartLoader::CachedSlice*>(layerSource.get()); |
150 } | 150 } |
151 else | 151 else |
152 { | 152 { |
153 layerSource.reset(new OrthancFrameLayerSource(IObserver::GetBroker(), orthancApiClient_)); | 153 layerSource.reset(new DicomSeriesVolumeSlicer(IObserver::GetBroker(), orthancApiClient_)); |
154 dynamic_cast<OrthancFrameLayerSource*>(layerSource.get())->SetImageQuality(imageQuality_); | 154 dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_); |
155 layerSource->RegisterObserverCallback(new Callable<SmartLoader, ILayerSource::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); | 155 layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); |
156 layerSource->RegisterObserverCallback(new Callable<SmartLoader, OrthancFrameLayerSource::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); | 156 layerSource->RegisterObserverCallback(new Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); |
157 layerSource->RegisterObserverCallback(new Callable<SmartLoader, ILayerSource::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); | 157 layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); |
158 dynamic_cast<OrthancFrameLayerSource*>(layerSource.get())->LoadFrame(instanceId, frame); | 158 dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame); |
159 } | 159 } |
160 | 160 |
161 // make sure that the widget registers the events before we trigger them | 161 // make sure that the widget registers the events before we trigger them |
162 if (sliceViewer.GetLayerCount() == layerIndex) | 162 if (sliceViewer.GetLayerCount() == layerIndex) |
163 { | 163 { |
180 } | 180 } |
181 | 181 |
182 void SmartLoader::PreloadSlice(const std::string instanceId, | 182 void SmartLoader::PreloadSlice(const std::string instanceId, |
183 unsigned int frame) | 183 unsigned int frame) |
184 { | 184 { |
185 // TODO: reactivate -> need to be able to ScheduleLayerLoading in ILayerSource without calling ScheduleLayerCreation | 185 // TODO: reactivate -> need to be able to ScheduleLayerLoading in IVolumeSlicer without calling ScheduleLayerCreation |
186 return; | 186 return; |
187 // TODO: check if it is already in the cache | 187 // TODO: check if it is already in the cache |
188 | 188 |
189 | 189 |
190 | 190 |
196 | 196 |
197 LOG(WARNING) << "Will preload: " << sliceKeyId; | 197 LOG(WARNING) << "Will preload: " << sliceKeyId; |
198 | 198 |
199 cachedSlices_[sliceKeyId] = boost::shared_ptr<CachedSlice>(cachedSlice); | 199 cachedSlices_[sliceKeyId] = boost::shared_ptr<CachedSlice>(cachedSlice); |
200 | 200 |
201 std::auto_ptr<ILayerSource> layerSource(new OrthancFrameLayerSource(IObserver::GetBroker(), orthancApiClient_)); | 201 std::auto_ptr<IVolumeSlicer> layerSource(new DicomSeriesVolumeSlicer(IObserver::GetBroker(), orthancApiClient_)); |
202 | 202 |
203 dynamic_cast<OrthancFrameLayerSource*>(layerSource.get())->SetImageQuality(imageQuality_); | 203 dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->SetImageQuality(imageQuality_); |
204 layerSource->RegisterObserverCallback(new Callable<SmartLoader, ILayerSource::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); | 204 layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::GeometryReadyMessage>(*this, &SmartLoader::OnLayerGeometryReady)); |
205 layerSource->RegisterObserverCallback(new Callable<SmartLoader, OrthancFrameLayerSource::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); | 205 layerSource->RegisterObserverCallback(new Callable<SmartLoader, DicomSeriesVolumeSlicer::FrameReadyMessage>(*this, &SmartLoader::OnFrameReady)); |
206 layerSource->RegisterObserverCallback(new Callable<SmartLoader, ILayerSource::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); | 206 layerSource->RegisterObserverCallback(new Callable<SmartLoader, IVolumeSlicer::LayerReadyMessage>(*this, &SmartLoader::OnLayerReady)); |
207 dynamic_cast<OrthancFrameLayerSource*>(layerSource.get())->LoadFrame(instanceId, frame); | 207 dynamic_cast<DicomSeriesVolumeSlicer*>(layerSource.get())->LoadFrame(instanceId, frame); |
208 | 208 |
209 // keep a ref to the LayerSource until the slice is fully loaded and saved to cache | 209 // keep a ref to the VolumeSlicer until the slice is fully loaded and saved to cache |
210 preloadingInstances_[sliceKeyId] = boost::shared_ptr<ILayerSource>(layerSource.release()); | 210 preloadingInstances_[sliceKeyId] = boost::shared_ptr<IVolumeSlicer>(layerSource.release()); |
211 } | 211 } |
212 | 212 |
213 | 213 |
214 // void PreloadStudy(const std::string studyId) | 214 // void PreloadStudy(const std::string studyId) |
215 // { | 215 // { |
220 // { | 220 // { |
221 // /* TODO */ | 221 // /* TODO */ |
222 // } | 222 // } |
223 | 223 |
224 | 224 |
225 void SmartLoader::OnLayerGeometryReady(const ILayerSource::GeometryReadyMessage& message) | 225 void SmartLoader::OnLayerGeometryReady(const IVolumeSlicer::GeometryReadyMessage& message) |
226 { | 226 { |
227 OrthancFrameLayerSource& source = dynamic_cast<OrthancFrameLayerSource&>(message.GetOrigin()); | 227 DicomSeriesVolumeSlicer& source = dynamic_cast<DicomSeriesVolumeSlicer&>(message.GetOrigin()); |
228 | 228 |
229 // save/replace the slice in cache | 229 // save/replace the slice in cache |
230 const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() | 230 const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() |
231 std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + | 231 std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + |
232 boost::lexical_cast<std::string>(slice.GetFrame())); | 232 boost::lexical_cast<std::string>(slice.GetFrame())); |
243 // re-emit original Layer message to observers | 243 // re-emit original Layer message to observers |
244 EmitMessage(message); | 244 EmitMessage(message); |
245 } | 245 } |
246 | 246 |
247 | 247 |
248 void SmartLoader::OnFrameReady(const OrthancFrameLayerSource::FrameReadyMessage& message) | 248 void SmartLoader::OnFrameReady(const DicomSeriesVolumeSlicer::FrameReadyMessage& message) |
249 { | 249 { |
250 // save/replace the slice in cache | 250 // save/replace the slice in cache |
251 const Slice& slice = message.GetSlice(); | 251 const Slice& slice = message.GetSlice(); |
252 std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + | 252 std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + |
253 boost::lexical_cast<std::string>(slice.GetFrame())); | 253 boost::lexical_cast<std::string>(slice.GetFrame())); |
265 // re-emit original Layer message to observers | 265 // re-emit original Layer message to observers |
266 EmitMessage(message); | 266 EmitMessage(message); |
267 } | 267 } |
268 | 268 |
269 | 269 |
270 void SmartLoader::OnLayerReady(const ILayerSource::LayerReadyMessage& message) | 270 void SmartLoader::OnLayerReady(const IVolumeSlicer::LayerReadyMessage& message) |
271 { | 271 { |
272 OrthancFrameLayerSource& source = dynamic_cast<OrthancFrameLayerSource&>(message.GetOrigin()); | 272 DicomSeriesVolumeSlicer& source = dynamic_cast<DicomSeriesVolumeSlicer&>(message.GetOrigin()); |
273 const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? | 273 const Slice& slice = source.GetSlice(0); // TODO handle GetSliceCount() ? |
274 std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + | 274 std::string sliceKeyId = (slice.GetOrthancInstanceId() + ":" + |
275 boost::lexical_cast<std::string>(slice.GetFrame())); | 275 boost::lexical_cast<std::string>(slice.GetFrame())); |
276 | 276 |
277 LOG(WARNING) << "Layer ready: " << sliceKeyId; | 277 LOG(WARNING) << "Layer ready: " << sliceKeyId; |