comparison Framework/Toolbox/OrthancSlicesLoader.cpp @ 247:3d523c9a8f0d am

trying to use boost::signals2 even more.
author am@osimis.io
date Mon, 02 Jul 2018 12:32:02 +0200
parents 5412adf19980
children
comparison
equal deleted inserted replaced
246:5470b15f7cf2 247:3d523c9a8f0d
167 return tmp.release(); 167 return tmp.release();
168 } 168 }
169 }; 169 };
170 170
171 171
172 class OrthancSlicesLoader::WebCallback : public IWebService::ICallback 172 // class OrthancSlicesLoader::WebCallback : public IWebService::ICallback
173 { 173 // {
174 private: 174 // private:
175 OrthancSlicesLoader& that_; 175 // OrthancSlicesLoader& that_;
176 176
177 public: 177 // public:
178 WebCallback(OrthancSlicesLoader& that) : 178 // WebCallback(OrthancSlicesLoader& that) :
179 that_(that) 179 // that_(that)
180 { 180 // {
181 } 181 // }
182 182
183 virtual void NotifySuccess(const std::string& uri, 183 void OrthancSlicesLoader::OnRequestSuccess(const std::string& uri,
184 const void* answer, 184 const void* answer,
185 size_t answerSize, 185 size_t answerSize,
186 Orthanc::IDynamicObject* payload) 186 Orthanc::IDynamicObject* payload)
187 { 187 {
188 std::auto_ptr<Operation> operation(dynamic_cast<Operation*>(payload)); 188 std::auto_ptr<Operation> operation(dynamic_cast<Operation*>(payload));
189 189
190 switch (operation->GetMode()) 190 switch (operation->GetMode())
191 { 191 {
192 case Mode_SeriesGeometry: 192 case Mode_SeriesGeometry:
193 that_.ParseSeriesGeometry(answer, answerSize); 193 ParseSeriesGeometry(answer, answerSize);
194 break; 194 break;
195 195
196 case Mode_InstanceGeometry: 196 case Mode_InstanceGeometry:
197 that_.ParseInstanceGeometry(operation->GetInstanceId(), answer, answerSize); 197 ParseInstanceGeometry(operation->GetInstanceId(), answer, answerSize);
198 break; 198 break;
199 199
200 case Mode_FrameGeometry: 200 case Mode_FrameGeometry:
201 that_.ParseFrameGeometry(operation->GetInstanceId(), 201 ParseFrameGeometry(operation->GetInstanceId(),
202 operation->GetFrame(), answer, answerSize); 202 operation->GetFrame(), answer, answerSize);
203 break; 203 break;
204 204
205 case Mode_LoadImage: 205 case Mode_LoadImage:
206 switch (operation->GetQuality()) 206 switch (operation->GetQuality())
207 { 207 {
208 case SliceImageQuality_Full: 208 case SliceImageQuality_Full:
209 that_.ParseSliceImagePng(*operation, answer, answerSize); 209 ParseSliceImagePng(*operation, answer, answerSize);
210 break; 210 break;
211 211
212 case SliceImageQuality_Jpeg50: 212 case SliceImageQuality_Jpeg50:
213 case SliceImageQuality_Jpeg90: 213 case SliceImageQuality_Jpeg90:
214 case SliceImageQuality_Jpeg95: 214 case SliceImageQuality_Jpeg95:
215 that_.ParseSliceImageJpeg(*operation, answer, answerSize); 215 ParseSliceImageJpeg(*operation, answer, answerSize);
216 break; 216 break;
217 217
218 default: 218 default:
219 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 219 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
220 } 220 }
221 221
222 break; 222 break;
223 223
224 case Mode_LoadRawImage: 224 case Mode_LoadRawImage:
225 that_.ParseSliceRawImage(*operation, answer, answerSize); 225 ParseSliceRawImage(*operation, answer, answerSize);
226 break; 226 break;
227 227
228 default: 228 default:
229 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 229 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
230 } 230 }
231 } 231 }
232 232
233 virtual void NotifyError(const std::string& uri, 233 void OrthancSlicesLoader::OnRequestError(const std::string& uri,
234 Orthanc::IDynamicObject* payload) 234 Orthanc::IDynamicObject* payload)
235 { 235 {
236 std::auto_ptr<Operation> operation(dynamic_cast<Operation*>(payload)); 236 std::auto_ptr<Operation> operation(dynamic_cast<Operation*>(payload));
237 LOG(ERROR) << "Cannot download " << uri; 237 LOG(ERROR) << "Cannot download " << uri;
238 238
239 switch (operation->GetMode()) 239 switch (operation->GetMode())
240 { 240 {
241 case Mode_FrameGeometry: 241 case Mode_FrameGeometry:
242 case Mode_SeriesGeometry: 242 case Mode_SeriesGeometry:
243 that_.userCallback_.NotifyGeometryError(that_); 243 SignalGeometryError(*this);
244 that_.state_ = State_Error; 244 state_ = State_Error;
245 break; 245 break;
246 246
247 case Mode_LoadImage: 247 case Mode_LoadImage:
248 that_.userCallback_.NotifySliceImageError(that_, operation->GetSliceIndex(), 248 SignalSliceImageError(*this, operation->GetSliceIndex(),
249 operation->GetSlice(), 249 operation->GetSlice(),
250 operation->GetQuality()); 250 operation->GetQuality());
251 break; 251 break;
252 252
253 default: 253 default:
254 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); 254 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
255 } 255 }
256 } 256 }
257 }; 257 // };
258 258
259 259
260 260
261 void OrthancSlicesLoader::NotifySliceImageSuccess(const Operation& operation, 261 void OrthancSlicesLoader::NotifySliceImageSuccess(const Operation& operation,
262 std::auto_ptr<Orthanc::ImageAccessor>& image) const 262 std::auto_ptr<Orthanc::ImageAccessor>& image) const
265 { 265 {
266 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 266 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
267 } 267 }
268 else 268 else
269 { 269 {
270 userCallback_.NotifySliceImageReady 270 SignalSliceImageReady(*this, operation.GetSliceIndex(), operation.GetSlice(), image, operation.GetQuality());
271 (*this, operation.GetSliceIndex(), operation.GetSlice(), image, operation.GetQuality());
272 } 271 }
273 } 272 }
274 273
275 274
276 void OrthancSlicesLoader::NotifySliceImageError(const Operation& operation) const 275 void OrthancSlicesLoader::NotifySliceImageError(const Operation& operation) const
277 { 276 {
278 userCallback_.NotifySliceImageError 277 SignalSliceImageError(*this, operation.GetSliceIndex(), operation.GetSlice(), operation.GetQuality());
279 (*this, operation.GetSliceIndex(), operation.GetSlice(), operation.GetQuality());
280 } 278 }
281 279
282 280
283 void OrthancSlicesLoader::SortAndFinalizeSlices() 281 void OrthancSlicesLoader::SortAndFinalizeSlices()
284 { 282 {
299 state_ = State_GeometryReady; 297 state_ = State_GeometryReady;
300 298
301 if (ok) 299 if (ok)
302 { 300 {
303 LOG(INFO) << "Loaded a series with " << slices_.GetSliceCount() << " slice(s)"; 301 LOG(INFO) << "Loaded a series with " << slices_.GetSliceCount() << " slice(s)";
304 userCallback_.NotifyGeometryReady(*this); 302 SignalGeometryReady(*this);
305 } 303 }
306 else 304 else
307 { 305 {
308 LOG(ERROR) << "This series is empty"; 306 LOG(ERROR) << "This series is empty";
309 userCallback_.NotifyGeometryError(*this); 307 SignalGeometryError(*this);
310 } 308 }
311 } 309 }
312 310
313 311
314 void OrthancSlicesLoader::ParseSeriesGeometry(const void* answer, 312 void OrthancSlicesLoader::ParseSeriesGeometry(const void* answer,
316 { 314 {
317 Json::Value series; 315 Json::Value series;
318 if (!MessagingToolbox::ParseJson(series, answer, size) || 316 if (!MessagingToolbox::ParseJson(series, answer, size) ||
319 series.type() != Json::objectValue) 317 series.type() != Json::objectValue)
320 { 318 {
321 userCallback_.NotifyGeometryError(*this); 319 SignalGeometryError(*this);
322 return; 320 return;
323 } 321 }
324 322
325 Json::Value::Members instances = series.getMemberNames(); 323 Json::Value::Members instances = series.getMemberNames();
326 324
363 { 361 {
364 Json::Value tags; 362 Json::Value tags;
365 if (!MessagingToolbox::ParseJson(tags, answer, size) || 363 if (!MessagingToolbox::ParseJson(tags, answer, size) ||
366 tags.type() != Json::objectValue) 364 tags.type() != Json::objectValue)
367 { 365 {
368 userCallback_.NotifyGeometryError(*this); 366 SignalGeometryError(*this);
369 return; 367 return;
370 } 368 }
371 369
372 OrthancPlugins::FullOrthancDataset dataset(tags); 370 OrthancPlugins::FullOrthancDataset dataset(tags);
373 371
390 slices_.AddSlice(slice.release()); 388 slices_.AddSlice(slice.release());
391 } 389 }
392 else 390 else
393 { 391 {
394 LOG(WARNING) << "Skipping invalid multi-frame instance " << instanceId; 392 LOG(WARNING) << "Skipping invalid multi-frame instance " << instanceId;
395 userCallback_.NotifyGeometryError(*this); 393 SignalGeometryError(*this);
396 return; 394 return;
397 } 395 }
398 } 396 }
399 397
400 SortAndFinalizeSlices(); 398 SortAndFinalizeSlices();
408 { 406 {
409 Json::Value tags; 407 Json::Value tags;
410 if (!MessagingToolbox::ParseJson(tags, answer, size) || 408 if (!MessagingToolbox::ParseJson(tags, answer, size) ||
411 tags.type() != Json::objectValue) 409 tags.type() != Json::objectValue)
412 { 410 {
413 userCallback_.NotifyGeometryError(*this); 411 SignalGeometryError(*this);
414 return; 412 return;
415 } 413 }
416 414
417 OrthancPlugins::FullOrthancDataset dataset(tags); 415 OrthancPlugins::FullOrthancDataset dataset(tags);
418 416
424 std::auto_ptr<Slice> slice(new Slice); 422 std::auto_ptr<Slice> slice(new Slice);
425 if (slice->ParseOrthancFrame(dicom, instanceId, frame)) 423 if (slice->ParseOrthancFrame(dicom, instanceId, frame))
426 { 424 {
427 LOG(INFO) << "Loaded instance " << instanceId; 425 LOG(INFO) << "Loaded instance " << instanceId;
428 slices_.AddSlice(slice.release()); 426 slices_.AddSlice(slice.release());
429 userCallback_.NotifyGeometryReady(*this); 427 SignalGeometryReady(*this);
430 } 428 }
431 else 429 else
432 { 430 {
433 LOG(WARNING) << "Skipping invalid instance " << instanceId; 431 LOG(WARNING) << "Skipping invalid instance " << instanceId;
434 userCallback_.NotifyGeometryError(*this); 432 SignalGeometryError(*this);
435 } 433 }
436 } 434 }
437 435
438 436
439 void OrthancSlicesLoader::ParseSliceImagePng(const Operation& operation, 437 void OrthancSlicesLoader::ParseSliceImagePng(const Operation& operation,
713 } 711 }
714 712
715 } 713 }
716 714
717 715
718 OrthancSlicesLoader::OrthancSlicesLoader(ICallback& callback, 716 OrthancSlicesLoader::OrthancSlicesLoader(boost::shared_ptr<OrthancSlicesLoader::IObserver> observer,
719 IWebService& orthanc) : 717 IWebService& orthanc) :
720 webCallback_(new WebCallback(*this)), 718 //webCallback_(new WebCallback(*this)),
721 userCallback_(callback), 719 // userCallback_(callback),
720 observer_(observer),
722 orthanc_(orthanc), 721 orthanc_(orthanc),
723 state_(State_Initialization) 722 state_(State_Initialization)
724 { 723 {
725 } 724 SignalGeometryReady.connect(OrthancSlicesLoader::IObserver::SignalGeometryReadyType::slot_type(&OrthancSlicesLoader::IObserver::NotifyGeometryReady, observer.get(), _1).track(observer));
726 725 SignalGeometryError.connect(OrthancSlicesLoader::IObserver::SignalGeometryErrorType::slot_type(&OrthancSlicesLoader::IObserver::NotifyGeometryError, observer.get(), _1).track(observer));
727 726 SignalSliceImageReady.connect(OrthancSlicesLoader::IObserver::SignalSliceImageReadyType::slot_type(&OrthancSlicesLoader::IObserver::NotifySliceImageReady, observer.get(), _1, _2, _3, _4, _5).track(observer));
728 void OrthancSlicesLoader::ScheduleLoadSeries(const std::string& seriesId) 727 SignalSliceImageError.connect(OrthancSlicesLoader::IObserver::SignalSliceImageErrorType::slot_type(&OrthancSlicesLoader::IObserver::NotifySliceImageError, observer.get(), _1, _2, _3, _4).track(observer));
728 }
729
730
731 void OrthancSlicesLoader::ScheduleLoadSeries(boost::shared_ptr<boost::noncopyable> tracker, const std::string& seriesId)
729 { 732 {
730 if (state_ != State_Initialization) 733 if (state_ != State_Initialization)
731 { 734 {
732 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 735 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
733 } 736 }
734 else 737 else
735 { 738 {
736 state_ = State_LoadingGeometry; 739 state_ = State_LoadingGeometry;
737 std::string uri = "/series/" + seriesId + "/instances-tags"; 740 std::string uri = "/series/" + seriesId + "/instances-tags";
738 orthanc_.ScheduleGetRequest(*webCallback_, uri, Operation::DownloadSeriesGeometry()); 741 orthanc_.ScheduleGetRequest(this, tracker, uri, Operation::DownloadSeriesGeometry());
739 } 742 }
740 } 743 }
741 744
742 745
743 void OrthancSlicesLoader::ScheduleLoadInstance(const std::string& instanceId) 746 void OrthancSlicesLoader::ScheduleLoadInstance(boost::shared_ptr<boost::noncopyable> tracker, const std::string& instanceId)
744 { 747 {
745 if (state_ != State_Initialization) 748 if (state_ != State_Initialization)
746 { 749 {
747 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 750 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
748 } 751 }
752 755
753 // Tag "3004-000c" is "Grid Frame Offset Vector", which is 756 // Tag "3004-000c" is "Grid Frame Offset Vector", which is
754 // mandatory to read RT DOSE, but is too long to be returned by default 757 // mandatory to read RT DOSE, but is too long to be returned by default
755 std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3004-000c"; 758 std::string uri = "/instances/" + instanceId + "/tags?ignore-length=3004-000c";
756 orthanc_.ScheduleGetRequest 759 orthanc_.ScheduleGetRequest
757 (*webCallback_, uri, Operation::DownloadInstanceGeometry(instanceId)); 760 (this, tracker, uri, Operation::DownloadInstanceGeometry(instanceId));
758 } 761 }
759 } 762 }
760 763
761 764
762 void OrthancSlicesLoader::ScheduleLoadFrame(const std::string& instanceId, 765 void OrthancSlicesLoader::ScheduleLoadFrame(boost::shared_ptr<boost::noncopyable> tracker, const std::string& instanceId,
763 unsigned int frame) 766 unsigned int frame)
764 { 767 {
765 if (state_ != State_Initialization) 768 if (state_ != State_Initialization)
766 { 769 {
767 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 770 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
769 else 772 else
770 { 773 {
771 state_ = State_LoadingGeometry; 774 state_ = State_LoadingGeometry;
772 std::string uri = "/instances/" + instanceId + "/tags"; 775 std::string uri = "/instances/" + instanceId + "/tags";
773 orthanc_.ScheduleGetRequest 776 orthanc_.ScheduleGetRequest
774 (*webCallback_, uri, Operation::DownloadFrameGeometry(instanceId, frame)); 777 (this, tracker, uri, Operation::DownloadFrameGeometry(instanceId, frame));
775 } 778 }
776 } 779 }
777 780
778 781
779 bool OrthancSlicesLoader::IsGeometryReady() const 782 bool OrthancSlicesLoader::IsGeometryReady() const
814 817
815 return slices_.LookupSlice(index, plane); 818 return slices_.LookupSlice(index, plane);
816 } 819 }
817 820
818 821
819 void OrthancSlicesLoader::ScheduleSliceImagePng(const Slice& slice, 822 void OrthancSlicesLoader::ScheduleSliceImagePng(boost::shared_ptr<boost::noncopyable> tracker, const Slice& slice,
820 size_t index) 823 size_t index)
821 { 824 {
822 std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + 825 std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" +
823 boost::lexical_cast<std::string>(slice.GetFrame())); 826 boost::lexical_cast<std::string>(slice.GetFrame()));
824 827
838 841
839 default: 842 default:
840 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 843 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
841 } 844 }
842 845
843 orthanc_.ScheduleGetRequest(*webCallback_, uri, 846 orthanc_.ScheduleGetRequest(this, tracker, uri,
844 Operation::DownloadSliceImage(index, slice, SliceImageQuality_Full)); 847 Operation::DownloadSliceImage(index, slice, SliceImageQuality_Full));
845 } 848 }
846 849
847 850
848 void OrthancSlicesLoader::ScheduleSliceImageJpeg(const Slice& slice, 851 void OrthancSlicesLoader::ScheduleSliceImageJpeg(boost::shared_ptr<boost::noncopyable> tracker, const Slice& slice,
849 size_t index, 852 size_t index,
850 SliceImageQuality quality) 853 SliceImageQuality quality)
851 { 854 {
852 unsigned int value; 855 unsigned int value;
853 856
873 std::string uri = ("/web-viewer/instances/jpeg" + 876 std::string uri = ("/web-viewer/instances/jpeg" +
874 boost::lexical_cast<std::string>(value) + 877 boost::lexical_cast<std::string>(value) +
875 "-" + slice.GetOrthancInstanceId() + "_" + 878 "-" + slice.GetOrthancInstanceId() + "_" +
876 boost::lexical_cast<std::string>(slice.GetFrame())); 879 boost::lexical_cast<std::string>(slice.GetFrame()));
877 880
878 orthanc_.ScheduleGetRequest(*webCallback_, uri, 881 orthanc_.ScheduleGetRequest(this, tracker, uri,
879 Operation::DownloadSliceImage(index, slice, quality)); 882 Operation::DownloadSliceImage(index, slice, quality));
880 } 883 }
881 884
882 885
883 886
884 void OrthancSlicesLoader::ScheduleLoadSliceImage(size_t index, 887 void OrthancSlicesLoader::ScheduleLoadSliceImage(boost::shared_ptr<boost::noncopyable> tracker, size_t index,
885 SliceImageQuality quality) 888 SliceImageQuality quality)
886 { 889 {
887 if (state_ != State_GeometryReady) 890 if (state_ != State_GeometryReady)
888 { 891 {
889 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); 892 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
893 896
894 if (slice.HasOrthancDecoding()) 897 if (slice.HasOrthancDecoding())
895 { 898 {
896 if (quality == SliceImageQuality_Full) 899 if (quality == SliceImageQuality_Full)
897 { 900 {
898 ScheduleSliceImagePng(slice, index); 901 ScheduleSliceImagePng(tracker, slice, index);
899 } 902 }
900 else 903 else
901 { 904 {
902 ScheduleSliceImageJpeg(slice, index, quality); 905 ScheduleSliceImageJpeg(tracker, slice, index, quality);
903 } 906 }
904 } 907 }
905 else 908 else
906 { 909 {
907 std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + 910 std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" +
908 boost::lexical_cast<std::string>(slice.GetFrame()) + "/raw.gz"); 911 boost::lexical_cast<std::string>(slice.GetFrame()) + "/raw.gz");
909 orthanc_.ScheduleGetRequest(*webCallback_, uri, 912 orthanc_.ScheduleGetRequest(this, tracker, uri,
910 Operation::DownloadSliceRawImage(index, slice)); 913 Operation::DownloadSliceRawImage(index, slice));
911 } 914 }
912 } 915 }
913 } 916 }