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;