SIRF  3.4.0
stir_data_containers.h
Go to the documentation of this file.
1 /*
2 SyneRBI Synergistic Image Reconstruction Framework (SIRF)
3 Copyright 2015 - 2019 Rutherford Appleton Laboratory STFC
4 Copyright 2018 - 2020 University College London
5 
6 This is software developed for the Collaborative Computational
7 Project in Synergistic Reconstruction for Biomedical Imaging (formerly CCP PETMR)
8 (http://www.ccpsynerbi.ac.uk/).
9 
10 Licensed under the Apache License, Version 2.0 (the "License");
11 you may not use this file except in compliance with the License.
12 You may obtain a copy of the License at
13 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19 
20 */
21 
32 #ifndef STIR_DATA_CONTAINER_TYPES
33 #define STIR_DATA_CONTAINER_TYPES
34 
35 #include <stdlib.h>
36 
37 #include <chrono>
38 #include <fstream>
39 #include <exception>
40 #include <iterator>
41 #include "sirf/STIR/stir_types.h"
42 #include "sirf/iUtilities/LocalisedException.h"
44 #include "sirf/common/iequals.h"
45 #include "sirf/common/JacobiCG.h"
46 #include "sirf/common/DataContainer.h"
47 #include "sirf/common/ANumRef.h"
48 #include "sirf/common/ImageData.h"
49 #include "sirf/common/GeometricalInfo.h"
50 #include "stir/ZoomOptions.h"
51 
52 #if STIR_VERSION < 050000
53 #define SPTR_WRAP(X) X->create_shared_clone()
54 #else
55 #define SPTR_WRAP(X) X
56 #endif
57 
58 namespace sirf {
59 
60  class SIRFUtilities {
61  public:
62  static long long milliseconds()
63  {
64  auto now = std::chrono::system_clock::now();
65  auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
66  return (long long)ms.count();
67  }
68  static std::string scratch_file_name()
69  {
70  static int calls = 0;
71  char buff[32];
72  long long int ms = milliseconds();
73  calls++;
74  sprintf(buff, "tmp_%d_%lld", calls, ms);
75  return std::string(buff);
76  }
77  };
78 
87  class ProjDataFile : public stir::ProjDataInterfile {
88 
89  public:
90  ProjDataFile(const stir::ProjData& pd, const std::string& filename, bool owns_file = true) :
91  stir::ProjDataInterfile(pd.get_exam_info_sptr(),
92  pd.get_proj_data_info_sptr()->create_shared_clone(),
93  filename, std::ios::in | std::ios::out | std::ios::trunc),
94  _filename(filename),
95  _owns_file(owns_file)
96  {}
97  ProjDataFile(stir::shared_ptr<const stir::ExamInfo> sptr_exam_info,
98  stir::shared_ptr<stir::ProjDataInfo> sptr_proj_data_info,
99  const std::string& filename, bool owns_file = true) :
100  stir::ProjDataInterfile(SPTR_WRAP(sptr_exam_info), SPTR_WRAP(sptr_proj_data_info),
101  filename, std::ios::in | std::ios::out | std::ios::trunc),
102  _filename(filename),
103  _owns_file(owns_file)
104  {}
105  ~ProjDataFile()
106  {
107  close_stream();
108  clear_stream();
109  if (!_owns_file)
110  return;
111  int err;
112  err = std::remove((_filename + ".hs").c_str());
113  if (err)
114  std::cout << "deleting " << _filename << ".hs "
115  << "failed, please delete manually" << std::endl;
116  err = std::remove((_filename + ".s").c_str());
117  if (err)
118  std::cout << "deleting " << _filename << ".s "
119  << "failed, please delete manually" << std::endl;
120  }
121  stir::shared_ptr<std::iostream> sino_stream_sptr()
122  {
123  return sino_stream;
124  }
125  void close_stream()
126  {
127  ((std::fstream*)sino_stream.get())->close();
128  }
129  void clear_stream()
130  {
131  ((std::fstream*)sino_stream.get())->clear();
132  }
133  private:
134  bool _owns_file;
135  std::string _filename;
136  };
137 
149  public:
150  virtual ~PETAcquisitionData() {}
151 
152  // virtual constructors
153  virtual PETAcquisitionData* same_acquisition_data
154  (stir::shared_ptr<const stir::ExamInfo> sptr_exam_info,
155  stir::shared_ptr<stir::ProjDataInfo> sptr_proj_data_info) const = 0;
156  virtual std::shared_ptr<PETAcquisitionData> new_acquisition_data() const = 0;
157 
158  virtual bool is_complex() const
159  {
160  return false;
161  }
162 
163  virtual std::unique_ptr<PETAcquisitionData> get_subset(const std::vector<int>& views) const = 0;
164 
166 
180  std::shared_ptr<PETAcquisitionData> single_slice_rebinned_data(
181  const int num_segments_to_combine,
182  const int num_views_to_combine = 1,
183  const int num_tang_poss_to_trim = 0,
184  const bool do_normalisation = true,
185  const int max_in_segment_num_to_process = -1,
186  const int num_tof_bins_to_combine = 1
187  )
188  {
189  stir::shared_ptr<stir::ProjDataInfo> out_proj_data_info_sptr(
190  stir::SSRB(*data()->get_proj_data_info_sptr(),
191  num_segments_to_combine,
192  num_views_to_combine,
193  num_tang_poss_to_trim,
194  max_in_segment_num_to_process,
195  num_tof_bins_to_combine
196  ));
197  std::shared_ptr<PETAcquisitionData>
198  sptr(same_acquisition_data
199  (this->get_exam_info_sptr(), out_proj_data_info_sptr));
200  stir::SSRB(*sptr, *data(), do_normalisation);
201  return sptr;
202  }
203 
204  static std::string storage_scheme()
205  {
206  static bool initialized = false;
207  if (!initialized) {
208  _storage_scheme = "file";
209  initialized = true;
210  }
211  return _storage_scheme;
212  }
213  static std::shared_ptr<PETAcquisitionData> storage_template()
214  {
215  return _template;
216  }
217 
218  stir::shared_ptr<stir::ProjData> data()
219  {
220  return _data;
221  }
222  const stir::shared_ptr<stir::ProjData> data() const
223  {
224  return _data;
225  }
226  void set_data(stir::shared_ptr<stir::ProjData> data)
227  {
228  _data = data;
229  }
230 
231  // data import/export
232  virtual void fill(const float v) { data()->fill(v); }
233  virtual void fill(const PETAcquisitionData& ad)
234  {
235  if (ad.is_empty())
236  THROW("The source of PETAcquisitionData::fill is empty");
237  stir::shared_ptr<stir::ProjData> sptr = ad.data();
238  data()->fill(*sptr);
239  }
240  virtual void fill_from(const float* d) { data()->fill_from(d); }
241  virtual void copy_to(float* d) const { data()->copy_to(d); }
242  std::unique_ptr<PETAcquisitionData> clone() const
243  {
244  return std::unique_ptr<PETAcquisitionData>(clone_impl());
245  }
246 
247  // data container methods
248  unsigned int items() const {
249  if (_is_empty != -1)
250  return _is_empty ? 0 : 1;
251  try {
252  get_segment_by_sinogram(0);
253  }
254  catch (std::string msg) {
255  _is_empty = 1;
256  return 0; // no data found - this must be a template
257  }
258  _is_empty = 0;
259  return 1; // data ok
260  }
261  virtual float norm() const;
262  virtual void dot(const DataContainer& a_x, void* ptr) const;
263  float dot(const DataContainer& a_x) const
264  {
265  float s;
266  dot(a_x, &s);
267  return s;
268  }
269  virtual void axpby(
270  const void* ptr_a, const DataContainer& a_x,
271  const void* ptr_b, const DataContainer& a_y);
272  virtual void xapyb(
273  const DataContainer& a_x, const void* ptr_a,
274  const DataContainer& a_y, const void* ptr_b);
275  virtual void xapyb(
276  const DataContainer& a_x, const DataContainer& a_a,
277  const DataContainer& a_y, const DataContainer& a_b);
278  virtual void multiply(const DataContainer& x, const DataContainer& y)
279  {
280  binary_op_(x, y, 1);
281  }
282  virtual void divide(const DataContainer& x, const DataContainer& y)
283  {
284  binary_op_(x, y, 2);
285  }
286  virtual void maximum(const DataContainer& x, const DataContainer& y)
287  {
288  binary_op_(x, y, 3);
289  }
290  virtual void minimum(const DataContainer& x, const DataContainer& y)
291  {
292  binary_op_(x, y, 4);
293  }
294  virtual void inv(float a, const DataContainer& x);
295  virtual void write(const std::string &filename) const
296  {
297  ProjDataFile pd(*data(), filename.c_str(), false);
298  pd.fill(*data());
299  }
300 
301  // ProjData methods
302  int get_num_tangential_poss()
303  {
304  return data()->get_num_tangential_poss();
305  }
306  int get_num_views()
307  {
308  return data()->get_num_views();
309  }
311 
314  int get_num_sinograms() const
315  {
316  return data()->get_num_sinograms();
317  }
319 
321  {
322  return data()->get_num_non_tof_sinograms();
323  }
324 
325  int get_num_TOF_bins()
326  {
327  return data()->get_num_tof_poss();
328  }
329 
330  int get_tof_mash_factor() const
331  {
332  return data()->get_proj_data_info_sptr()->get_tof_mash_factor();
333  }
334 
335  size_t get_dimensions(int* dim)
336  {
337  dim[0] = get_num_tangential_poss();
338  dim[1] = get_num_views();
339  dim[2] = get_num_non_TOF_sinograms();
340  dim[3] = get_num_TOF_bins();
341  return static_cast<size_t>(dim[0] * dim[1] * dim[2] * dim[3]);
342  }
343  int get_max_segment_num() const
344  {
345  return data()->get_max_segment_num();
346  }
347  stir::SegmentBySinogram<float>
348  get_segment_by_sinogram(const int segment_num) const
349  {
350  return data()->get_segment_by_sinogram(segment_num);
351  }
352  stir::SegmentBySinogram<float>
353  get_empty_segment_by_sinogram(const int segment_num) const
354  {
355  return data()->get_empty_segment_by_sinogram(segment_num);
356  }
357  void set_segment(const stir::SegmentBySinogram<float>& s)
358  {
359  if (data()->set_segment(s) != stir::Succeeded::yes)
360  THROW("stir::ProjData set segment failed");
361  }
362  stir::shared_ptr<const stir::ExamInfo> get_exam_info_sptr() const
363  {
364  return data()->get_exam_info_sptr();
365  }
366  stir::shared_ptr<const stir::ProjDataInfo> get_proj_data_info_sptr() const
367  {
368  return data()->get_proj_data_info_sptr();
369  }
370 
371  // ProjData casts
372  operator stir::ProjData&() { return *data(); }
373  operator const stir::ProjData&() const { return *data(); }
374  operator stir::shared_ptr<stir::ProjData>() { return data(); }
375 
376  static stir::shared_ptr<stir::ProjDataInfo>
377  proj_data_info_from_scanner(std::string scanner_name,
378  int span = 1, int max_ring_diff = -1, int view_mash_factor = 1)
379  {
380  stir::shared_ptr<stir::Scanner>
381  sptr_s(stir::Scanner::get_scanner_from_name(scanner_name));
382  //std::cout << "scanner: " << sptr_s->get_name().c_str() << '\n';
383  if (sirf::iequals(sptr_s->get_name(), "unknown")) {
384  throw LocalisedException("Unknown scanner", __FILE__, __LINE__);
385  }
386  int num_views = sptr_s->get_num_detectors_per_ring() / 2 / view_mash_factor;
387  int num_tang_pos = sptr_s->get_max_num_non_arccorrected_bins();
388  if (max_ring_diff < 0)
389  max_ring_diff = sptr_s->get_num_rings() - 1;
390  return std::move(stir::ProjDataInfo::construct_proj_data_info
391  (sptr_s, span, max_ring_diff, num_views, num_tang_pos, false));
392  }
393 
394  protected:
395  static std::string _storage_scheme;
396  static std::shared_ptr<PETAcquisitionData> _template;
397  stir::shared_ptr<stir::ProjData> _data;
398  virtual PETAcquisitionData* clone_impl() const = 0;
399  PETAcquisitionData* clone_base() const
400  {
401  stir::shared_ptr<stir::ProjDataInfo> sptr_pdi = this->get_proj_data_info_sptr()->create_shared_clone();
402  PETAcquisitionData* ptr =
403  _template->same_acquisition_data(this->get_exam_info_sptr(), sptr_pdi);
404  if (!this->is_empty())
405  ptr->fill(*this);
406  return ptr;
407  }
408 
409  private:
410  mutable int _is_empty = -1;
411  void binary_op_(const DataContainer& a_x, const DataContainer& a_y, int job);
412  };
413 
421  public:
422  PETAcquisitionDataInFile() : _owns_file(false) {}
423  PETAcquisitionDataInFile(const char* filename) : _owns_file(false)
424  {
425  _data = stir::ProjData::read_from_file(filename);
426  }
427  PETAcquisitionDataInFile(stir::shared_ptr<const stir::ExamInfo> sptr_exam_info,
428  stir::shared_ptr<stir::ProjDataInfo> sptr_proj_data_info)
429  {
430  _data.reset(new ProjDataFile
431  (MAKE_SHARED<stir::ExamInfo>(*sptr_exam_info), sptr_proj_data_info,
432  _filename = SIRFUtilities::scratch_file_name()));
433  }
434  PETAcquisitionDataInFile(const stir::ProjData& pd) : _owns_file(true)
435  {
436  _data.reset(new ProjDataFile
437  (pd, _filename = SIRFUtilities::scratch_file_name()));
438  }
440  (stir::shared_ptr<stir::ExamInfo> sptr_ei, std::string scanner_name,
441  int span = 1, int max_ring_diff = -1, int view_mash_factor = 1)
442  {
443  stir::shared_ptr<stir::ProjDataInfo> sptr_pdi =
444  PETAcquisitionData::proj_data_info_from_scanner
445  (scanner_name, span, max_ring_diff, view_mash_factor);
446  ProjDataFile* ptr = new ProjDataFile(sptr_ei, sptr_pdi,
447  _filename = SIRFUtilities::scratch_file_name());
448  ptr->fill(0.0f);
449  _data.reset(ptr);
450  }
451  PETAcquisitionDataInFile(std::unique_ptr<stir::ProjData> uptr_pd) : _owns_file(true)
452  {
453 // auto *pd_ptr = dynamic_cast<stir::ProjDataInterfile*>(uptr_pd.get());
454  auto pd_ptr = dynamic_cast<stir::ProjDataInterfile*>(uptr_pd.get());
455  if (pd_ptr)
456  _data = std::move(uptr_pd);
457  else {
458  stir::ProjData& pd = *uptr_pd;
459  stir::shared_ptr<const stir::ExamInfo> sptr_exam_info =
460  pd.get_exam_info_sptr();
461  stir::shared_ptr<stir::ProjDataInfo> sptr_proj_data_info =
462  pd.get_proj_data_info_sptr()->create_shared_clone();
463  _data.reset(new ProjDataFile
464  (MAKE_SHARED<stir::ExamInfo>(*sptr_exam_info), sptr_proj_data_info,
465  _filename = SIRFUtilities::scratch_file_name()));
466  _data->fill(pd);
467  }
468  }
469  std::shared_ptr<PETAcquisitionData> new_acquisition_data(std::string filename)
470  {
471  std::shared_ptr<PETAcquisitionDataInFile> sptr_ad(new PETAcquisitionDataInFile);
472  sptr_ad->_data.reset(new ProjDataFile(*data(), filename, false));
473  return sptr_ad;
474  }
475 
476  static void init() {
477  static bool initialized = false;
478  if (!initialized) {
479  _storage_scheme = "file";
480  _template.reset(new PETAcquisitionDataInFile());
481  initialized = true;
482  PETAcquisitionData::storage_scheme();
483  }
484  }
485  static void set_as_template()
486  {
487  init();
488  _storage_scheme = "file";
489  _template.reset(new PETAcquisitionDataInFile);
490  }
491 
492  virtual PETAcquisitionData* same_acquisition_data
493  (stir::shared_ptr<const stir::ExamInfo> sptr_exam_info,
494  stir::shared_ptr<stir::ProjDataInfo> sptr_proj_data_info) const
495  {
496  PETAcquisitionData* ptr_ad =
497  new PETAcquisitionDataInFile(sptr_exam_info, sptr_proj_data_info);
498  return ptr_ad;
499  }
500  virtual ObjectHandle<DataContainer>* new_data_container_handle() const
501  {
502  init();
503  DataContainer* ptr = _template->same_acquisition_data(
504  this->get_exam_info_sptr(),
505  this->get_proj_data_info_sptr()->create_shared_clone());
506  return new ObjectHandle<DataContainer>
507  (std::shared_ptr<DataContainer>(ptr));
508  }
509  virtual std::shared_ptr<PETAcquisitionData> new_acquisition_data() const
510  {
511  init();
512  return std::shared_ptr < PETAcquisitionData >
513  (_template->same_acquisition_data(this->get_exam_info_sptr(),
514  this->get_proj_data_info_sptr()->create_shared_clone()));
515  }
516  virtual std::unique_ptr<PETAcquisitionData> get_subset(const std::vector<int>& views) const;
517 
518  private:
519  bool _owns_file;
520  std::string _filename;
521  virtual PETAcquisitionDataInFile* clone_impl() const
522  {
523  init();
524  return (PETAcquisitionDataInFile*)clone_base();
525  }
526  };
527 
535  public:
537  PETAcquisitionDataInMemory(stir::shared_ptr<const stir::ExamInfo> sptr_exam_info,
538  stir::shared_ptr<const stir::ProjDataInfo> sptr_proj_data_info)
539  {
540  _data = stir::shared_ptr<stir::ProjData>
541  (new stir::ProjDataInMemory(SPTR_WRAP(sptr_exam_info), SPTR_WRAP(sptr_proj_data_info)));
542  }
543  PETAcquisitionDataInMemory(const stir::ProjData& templ)
544  {
545  _data = stir::shared_ptr<stir::ProjData>
546  (new stir::ProjDataInMemory(templ.get_exam_info_sptr(),
547  templ.get_proj_data_info_sptr()->create_shared_clone()));
548  }
550  (stir::shared_ptr<stir::ExamInfo> sptr_ei, std::string scanner_name,
551  int span = 1, int max_ring_diff = -1, int view_mash_factor = 1)
552  {
553  stir::shared_ptr<stir::ProjDataInfo> sptr_pdi =
554  PETAcquisitionData::proj_data_info_from_scanner
555  (scanner_name, span, max_ring_diff, view_mash_factor);
556  stir::ProjDataInMemory* ptr = new stir::ProjDataInMemory(sptr_ei, sptr_pdi);
557  ptr->fill(0.0f);
558  _data.reset(ptr);
559  }
560  PETAcquisitionDataInMemory(std::unique_ptr<stir::ProjData> uptr_pd)
561  {
562 // auto *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(uptr_pd.get());
563  auto pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(uptr_pd.get());
564  if (pd_ptr)
565  _data = std::move(uptr_pd);
566  else {
567  std::cout << "copying ProjData to ProjDataInMemory...\n";
568  const stir::ProjData& pd = *uptr_pd;
569  auto exam_info_sptr = SPTR_WRAP(pd.get_exam_info_sptr());
570  auto proj_data_info_sptr =
571  SPTR_WRAP(pd.get_proj_data_info_sptr()->create_shared_clone());
572  _data.reset(new stir::ProjDataInMemory(exam_info_sptr, proj_data_info_sptr));
573  _data->fill(pd);
574  }
575  }
577  PETAcquisitionDataInMemory(const char* filename)
578  {
579  auto pd_sptr = stir::ProjData::read_from_file(filename);
580  bool is_empty = false;
581  try {
582  pd_sptr->get_segment_by_sinogram(0);
583  }
584  catch (...) {
585  is_empty = true;
586  }
587  if (is_empty)
588  _data = stir::shared_ptr<stir::ProjData>
589  (new stir::ProjDataInMemory(pd_sptr->get_exam_info_sptr(),
590  pd_sptr->get_proj_data_info_sptr()->create_shared_clone()));
591  else
592  _data = stir::shared_ptr<stir::ProjData>
593  (new stir::ProjDataInMemory(*pd_sptr));
594  }
595 
596  static void init();
597 
598  static void set_as_template()
599  {
600  init();
601  _storage_scheme = "memory";
602  _template.reset(new PETAcquisitionDataInMemory);
603  }
604 
605  virtual PETAcquisitionData* same_acquisition_data
606  (stir::shared_ptr<const stir::ExamInfo> sptr_exam_info,
607  stir::shared_ptr<stir::ProjDataInfo> sptr_proj_data_info) const
608  {
609  PETAcquisitionData* ptr_ad =
610  new PETAcquisitionDataInMemory(sptr_exam_info, sptr_proj_data_info);
611  return ptr_ad;
612  }
613  virtual ObjectHandle<DataContainer>* new_data_container_handle() const
614  {
615  init();
616  DataContainer* ptr = _template->same_acquisition_data
617  (this->get_exam_info_sptr(),
618  this->get_proj_data_info_sptr()->create_shared_clone());
619  return new ObjectHandle<DataContainer>
620  (std::shared_ptr<DataContainer>(ptr));
621  }
622  virtual std::shared_ptr<PETAcquisitionData> new_acquisition_data() const
623  {
624  init();
625  return std::shared_ptr < PETAcquisitionData >
626  (_template->same_acquisition_data
627  (this->get_exam_info_sptr(),
628  this->get_proj_data_info_sptr()->create_shared_clone()));
629  }
630  virtual std::unique_ptr<PETAcquisitionData> get_subset(const std::vector<int>& views) const;
631 
633  virtual void fill(const float v)
634  {
635  stir::ProjDataInMemory *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(data().get());
636  // If cast failed, fall back to general method
637  if (is_null_ptr(pd_ptr))
638  return this->PETAcquisitionData::fill(v);
639 
640  // do it
641  auto iter = pd_ptr->begin();
642  while (iter != pd_ptr->end())
643  *iter++ = v;
644  }
646  virtual void fill(const PETAcquisitionData& ad)
647  {
648  // Can only do this if both are PETAcquisitionDataInMemory
649  stir::ProjDataInMemory *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(data().get());
650  const stir::ProjDataInMemory *pd2_ptr = dynamic_cast<const stir::ProjDataInMemory*>(ad.data().get());
651  // If either cast failed, fall back to general method
652  if (is_null_ptr(pd_ptr) || is_null_ptr(pd2_ptr))
653  return this->PETAcquisitionData::fill(ad);
654 
655  // do it
656  auto iter = pd_ptr->begin();
657  auto iter_other = pd2_ptr->begin();
658  while (iter != pd_ptr->end())
659  *iter++ = *iter_other++;
660  }
662  virtual void fill_from(const float* d)
663  {
664  stir::ProjDataInMemory *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(data().get());
665  // If cast failed, fall back to general method
666  if (is_null_ptr(pd_ptr))
667  return this->PETAcquisitionData::fill_from(d);
668 
669  // do it
670  auto iter = pd_ptr->begin();
671  while (iter != pd_ptr->end())
672  *iter++ = *d++;
673  }
675  virtual void copy_to(float* d) const
676  {
677  const stir::ProjDataInMemory *pd_ptr = dynamic_cast<const stir::ProjDataInMemory*>(data().get());
678  // If cast failed, fall back to general method
679  if (is_null_ptr(pd_ptr))
680  return this->PETAcquisitionData::copy_to(d);
681 
682  // do it
683  auto iter = pd_ptr->begin();
684  while (iter != pd_ptr->end())
685  *d++ = *iter++;
686  }
687  virtual float norm() const
688  {
689  const stir::ProjDataInMemory *pd_ptr = dynamic_cast<const stir::ProjDataInMemory*>(data().get());
690  // If cast failed, fall back to general method
691  if (is_null_ptr(pd_ptr))
692  return this->PETAcquisitionData::norm();
693 
694  // do it
695  double t = 0.0;
696  auto iter = pd_ptr->begin();
697  for (; iter != pd_ptr->end(); ++iter)
698  t += (*iter) * (*iter);
699  return sqrt((float)t);
700  }
701  virtual void dot(const DataContainer& a_x, void* ptr) const
702  {
703  auto x = dynamic_cast<const PETAcquisitionData*>(&a_x);
704  // Can only do this if both are PETAcquisitionDataInMemory
705  stir::ProjDataInMemory *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(data().get());
706  const stir::ProjDataInMemory *pd2_ptr = dynamic_cast<const stir::ProjDataInMemory*>(x->data().get());
707  // If either cast failed, fall back to general method
708  if (is_null_ptr(pd_ptr) || is_null_ptr(pd2_ptr))
709  return this->PETAcquisitionData::dot(a_x,ptr);
710 
711  // do it
712  double t = 0.0;
713  auto iter = pd_ptr->begin();
714  auto iter_other = pd2_ptr->begin();
715  while (iter != pd_ptr->end())
716  t += (*iter++) * (*iter_other++);
717 
718  float* ptr_t = (float*)ptr;
719  *ptr_t = (float)t;
720  }
721  virtual void multiply(const DataContainer& x, const DataContainer& y)
722  {
723  auto a_x = dynamic_cast<const PETAcquisitionData*>(&x);
724  auto a_y = dynamic_cast<const PETAcquisitionData*>(&y);
725 
726  // Can only do this if all are PETAcquisitionDataInMemory
727  auto *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(data().get());
728  auto *pd_x_ptr = dynamic_cast<const stir::ProjDataInMemory*>(a_x->data().get());
729  auto *pd_y_ptr = dynamic_cast<const stir::ProjDataInMemory*>(a_y->data().get());
730 
731  // If either cast failed, fall back to general method
732  if (is_null_ptr(pd_ptr) || is_null_ptr(pd_x_ptr) || is_null_ptr(pd_x_ptr))
733  return this->PETAcquisitionData::multiply(x,y);
734 
735  // do it
736  auto iter = pd_ptr->begin();
737  auto iter_x = pd_x_ptr->begin();
738  auto iter_y = pd_y_ptr->begin();
739  while (iter != pd_ptr->end())
740  *iter++ = (*iter_x++) * (*iter_y++);
741  }
742  virtual void divide(const DataContainer& x, const DataContainer& y)
743  {
744  auto a_x = dynamic_cast<const PETAcquisitionData*>(&x);
745  auto a_y = dynamic_cast<const PETAcquisitionData*>(&y);
746 
747  // Can only do this if all are PETAcquisitionDataInMemory
748  auto *pd_ptr = dynamic_cast<stir::ProjDataInMemory*>(data().get());
749  auto *pd_x_ptr = dynamic_cast<const stir::ProjDataInMemory*>(a_x->data().get());
750  auto *pd_y_ptr = dynamic_cast<const stir::ProjDataInMemory*>(a_y->data().get());
751 
752  // If either cast failed, fall back to general method
753  if (is_null_ptr(pd_ptr) || is_null_ptr(pd_x_ptr) || is_null_ptr(pd_x_ptr))
754  return this->PETAcquisitionData::divide(x,y);
755 
756  // do it
757  auto iter = pd_ptr->begin();
758  auto iter_x = pd_x_ptr->begin();
759  auto iter_y = pd_y_ptr->begin();
760  while (iter != pd_ptr->end())
761  *iter++ = (*iter_x++) / (*iter_y++);
762  }
763 
764  private:
765  virtual PETAcquisitionDataInMemory* clone_impl() const
766  {
767  init();
768  return (PETAcquisitionDataInMemory*)clone_base();
769  }
770  };
771 
772  typedef Image3DF::full_iterator Image3DFIterator;
773  typedef Image3DF::const_full_iterator Image3DFIterator_const;
774 
783  class STIRImageData : public ImageData {
784  public:
787  class Iterator : public BaseIter {
788  public:
790 
791  typedef Image3DFIterator::difference_type difference_type;
792  typedef Image3DFIterator::value_type value_type;
793  typedef Image3DFIterator::reference reference;
794  typedef Image3DFIterator::pointer pointer;
795  typedef std::forward_iterator_tag iterator_category;
797  Iterator(const Image3DFIterator& iter) : _iter(iter)
798  {}
799  Iterator& operator=(const Iterator& iter)
800  {
801  _iter = iter._iter;
802  _ref.copy(iter._ref);
803  _sptr_iter = iter._sptr_iter;
804  return *this;
805  }
806  virtual Iterator& operator++()
807  {
808  ++_iter;
809  return *this;
810  }
811  //virtual Iterator& operator++(int)
812  //{
813  // _sptr_iter.reset(new Iterator(_iter));
814  // ++_iter;
815  // return *_sptr_iter;
816  //}
817  virtual bool operator==(const BaseIter& an_iter) const
818  {
819  const Iterator& iter = (const Iterator&)an_iter;
820  return _iter == iter._iter;
821  }
822  virtual bool operator!=(const BaseIter& an_iter) const
823  {
824  const Iterator& iter = (const Iterator&)an_iter;
825  return _iter != iter._iter;
826  }
827  virtual FloatRef& operator*()
828  {
829  float& v = *_iter;
830  _ref.set_ptr(&v);
831  return _ref;
832  }
833  private:
834  Image3DFIterator _iter;
835  FloatRef _ref;
836  std::shared_ptr<Iterator> _sptr_iter;
837  };
838  class Iterator_const : public BaseIter_const {
839  public:
840  Iterator_const(const Image3DFIterator_const& iter) : _iter(iter)
841  {}
842  Iterator_const& operator=(const Iterator_const& iter)
843  {
844  _iter = iter._iter;
845  _ref.copy(iter._ref);
846  _sptr_iter = iter._sptr_iter;
847  return *this;
848  }
849  virtual Iterator_const& operator++()
850  {
851  ++_iter;
852  return *this;
853  }
854  //virtual Iterator_const& operator++(int)
855  //{
856  // _sptr_iter.reset(new Iterator_const(_iter));
857  // ++_iter;
858  // return *_sptr_iter;
859  //}
860  virtual bool operator==(const BaseIter_const& an_iter) const
861  {
862  const Iterator_const& iter = (const Iterator_const&)an_iter;
863  return _iter == iter._iter;
864  }
865  virtual bool operator!=(const BaseIter_const& an_iter) const
866  {
867  const Iterator_const& iter = (const Iterator_const&)an_iter;
868  return _iter != iter._iter;
869  }
870  virtual const FloatRef& operator*() const
871  {
872  const float& v = *_iter;
873  _ref.set_ptr((void*)&v);
874  return _ref;
875  }
876  private:
877  Image3DFIterator_const _iter;
878  mutable FloatRef _ref;
879  std::shared_ptr<Iterator_const> _sptr_iter;
880  };
881  STIRImageData() {}
882  STIRImageData(const ImageData& id);
883  STIRImageData(const STIRImageData& image)
884  {
885  _data.reset(image.data().clone());
886  this->set_up_geom_info();
887  }
889  {
890  _data.reset(new Voxels3DF(MAKE_SHARED<stir::ExamInfo>(*ad.get_exam_info_sptr()),*ad.get_proj_data_info_sptr()));
891  this->set_up_geom_info();
892  }
893  STIRImageData(const Image3DF& image)
894  {
895  _data.reset(image.clone());
896  this->set_up_geom_info();
897  }
898  STIRImageData(const Voxels3DF& v)
899  {
900  _data.reset(v.clone());
901  this->set_up_geom_info();
902  }
903  STIRImageData(const stir::ProjDataInfo& pdi)
904  {
905  _data.reset(new Voxels3DF(pdi));
906  this->set_up_geom_info();
907  }
908  STIRImageData(stir::shared_ptr<Image3DF> ptr)
909  {
910  _data = ptr;
911  this->set_up_geom_info();
912  }
913  STIRImageData(std::string filename)
914  {
915  _data = stir::read_from_file<Image3DF>(filename);
916  this->set_up_geom_info();
917  }
918  STIRImageData* same_image_data() const
919  {
920  STIRImageData* ptr_image = new STIRImageData;
921  ptr_image->_data.reset(_data->get_empty_copy());
922  ptr_image->set_up_geom_info();
923  return ptr_image;
924  }
925  std::shared_ptr<STIRImageData> new_image_data()
926  {
927  return std::shared_ptr<STIRImageData>(same_image_data());
928  }
929  virtual ObjectHandle<DataContainer>* new_data_container_handle() const
930  {
931  return new ObjectHandle<DataContainer>
932  (std::shared_ptr<DataContainer>(same_image_data()));
933  }
934  virtual bool is_complex() const
935  {
936  return false;
937  }
938  unsigned int items() const
939  {
940  return 1;
941  }
942 
943  std::string modality() const
944  {
945  ExamInfo ex_info = data().get_exam_info();
946  return ex_info.imaging_modality.get_name();
947  }
948  void set_modality(const std::string& mod)
949  {
950  ExamInfo ex_info = data().get_exam_info();
951  ex_info.imaging_modality = ImagingModality(mod);
952  data().set_exam_info(ex_info);
953  }
954 
956  virtual void write(const std::string &filename) const;
958 
976  virtual void write(const std::string &filename, const std::string &format_file) const;
977 
978  virtual float norm() const;
979  virtual void dot(const DataContainer& a_x, void* ptr) const;
980  virtual void axpby(
981  const void* ptr_a, const DataContainer& a_x,
982  const void* ptr_b, const DataContainer& a_y);
983  virtual void xapyb(
984  const DataContainer& a_x, const void* ptr_a,
985  const DataContainer& a_y, const void* ptr_b);
986  virtual void xapyb(
987  const DataContainer& a_x, const DataContainer& a_a,
988  const DataContainer& a_y, const DataContainer& a_b);
989  virtual void multiply(const DataContainer& x, const DataContainer& y)
990  {
991  binary_op_(x, y, 1);
992  }
993  virtual void divide(const DataContainer& x, const DataContainer& y)
994  {
995  binary_op_(x, y, 2);
996  }
997  virtual void maximum(const DataContainer& x, const DataContainer& y)
998  {
999  binary_op_(x, y, 3);
1000  }
1001  virtual void minimum(const DataContainer& x, const DataContainer& y)
1002  {
1003  binary_op_(x, y, 4);
1004  }
1005 
1006  Image3DF& data()
1007  {
1008  return *_data;
1009  }
1010  const Image3DF& data() const
1011  {
1012  return *_data;
1013  }
1014  Image3DF* data_ptr()
1015  {
1016  return _data.get();
1017  }
1018  const Image3DF* data_ptr() const
1019  {
1020  return _data.get();
1021  }
1022  stir::shared_ptr<Image3DF> data_sptr()
1023  {
1024  return _data;
1025  }
1026  stir::shared_ptr<const Image3DF> data_sptr() const
1027  {
1028  return _data;
1029  }
1030  void set_data_sptr(stir::shared_ptr<Image3DF> sptr_data)
1031  {
1032  _data = sptr_data;
1033  }
1034 
1035  void fill(float v)
1036  {
1037  _data->fill(v);
1038  }
1039  void scale(float s);
1040  float dot(const DataContainer& a_x) const
1041  {
1042  float s;
1043  dot(a_x, &s);
1044  return s;
1045  }
1046  void axpby(
1047  float a, const DataContainer& a_x,
1048  float b, const DataContainer& a_y)
1049  {
1050  axpby(&a, a_x, &b, a_y);
1051  }
1052  void xapyb(
1053  const DataContainer& a_x, float a,
1054  const DataContainer& a_y, float b)
1055  {
1056  xapyb(a_x, &a, a_y, &b);
1057  }
1058  virtual Dimensions dimensions() const
1059  {
1060  Dimensions dim;
1061  int d[4];
1062  get_dimensions(d);
1063  dim["z"] = d[0];
1064  dim["y"] = d[1];
1065  dim["x"] = d[2];
1066  return dim;
1067  }
1068  int get_dimensions(int* dim) const;
1069  void get_voxel_sizes(float* vsizes) const;
1070  virtual void get_data(float* data) const;
1071  virtual void set_data(const float* data);
1072  virtual Iterator& begin()
1073  {
1074  _begin.reset(new Iterator(data().begin_all()));
1075  return *_begin;
1076  }
1077  virtual Iterator_const& begin() const
1078  {
1079  _begin_const.reset(new Iterator_const(data().begin_all()));
1080  return *_begin_const;
1081  }
1082  virtual Iterator& end()
1083  {
1084  _end.reset(new Iterator(data().end_all()));
1085  return *_end;
1086  }
1087  virtual Iterator_const& end() const
1088  {
1089  _end_const.reset(new Iterator_const(data().end_all()));
1090  return *_end_const;
1091  }
1092 
1094  std::unique_ptr<STIRImageData> clone() const
1095  {
1096  return std::unique_ptr<STIRImageData>(this->clone_impl());
1097  }
1098 
1102  void zoom_image(const Coord3DF &zooms={1.f,1.f,1.f}, const Coord3DF &offsets_in_mm={0.f,0.f,0.f},
1103  const Coord3DI &new_sizes={-1,-1,-1}, const char * const zoom_options_str="preserve_sum");
1104 
1108  void zoom_image(const Coord3DF &zooms={1.f,1.f,1.f}, const Coord3DF &offsets_in_mm={0.f,0.f,0.f},
1109  const Coord3DI &new_sizes={-1,-1,-1},
1110  const stir::ZoomOptions zoom_options=stir::ZoomOptions::preserve_sum);
1111 
1114  void move_to_scanner_centre(const PETAcquisitionData &);
1115 
1117  virtual void set_up_geom_info();
1118 
1119  private:
1121  virtual STIRImageData* clone_impl() const
1122  {
1123  return new STIRImageData(*this);
1124  }
1125  void binary_op_(const DataContainer& a_x, const DataContainer& a_y, int job);
1126 
1127  protected:
1128 
1129  stir::shared_ptr<Image3DF> _data;
1130  mutable std::shared_ptr<Iterator> _begin;
1131  mutable std::shared_ptr<Iterator> _end;
1132  mutable std::shared_ptr<Iterator_const> _begin_const;
1133  mutable std::shared_ptr<Iterator_const> _end_const;
1134  };
1135 
1136 } // namespace sirf
1137 
1138 #endif
Definition: ImageData.h:37
STIR DiscretisedDensity<3, float> wrapper with added functionality.
Definition: stir_data_containers.h:783
Definition: LocalisedException.h:32
virtual void multiply(const DataContainer &x, const DataContainer &y)
*this = the elementwise product x*y
Definition: stir_data_containers.h:989
bool iequals(const std::string &a, const std::string &b)
Case insensitive string comparison, replaces boost::iequals.
Definition: iequals.cpp:7
Case insensitive string comparison sirf::iequals.
virtual void dot(const DataContainer &a_x, void *ptr) const
calculates the dot product of this container with another one
Definition: stir_data_containers.cpp:60
virtual bool is_complex() const
Is complex? Unless overwridden (Gadgetron), assume not complex.
Definition: stir_data_containers.h:934
virtual void fill_from(const float *d)
Fill from float array.
Definition: stir_data_containers.h:662
int get_num_non_TOF_sinograms() const
total number of (2D) sinograms ignoring time-of-flight
Definition: stir_data_containers.h:320
Definition: ANumRef.h:68
void err(const std::string &message)
throw error
Definition: sirf_convert_image_type.cpp:115
std::unique_ptr< STIRImageData > clone() const
Clone and return as unique pointer.
Definition: stir_data_containers.h:1094
Definition: ImageData.h:52
In-memory implementation of PETAcquisitionData.
Definition: stir_data_containers.h:534
Definition: stir_data_containers.h:787
Definition: ImageData.h:44
In-file implementation of PETAcquisitionData.
Definition: stir_data_containers.h:420
virtual void minimum(const DataContainer &x, const DataContainer &y)
*this = the elementwise min(x, y)
Definition: stir_data_containers.h:290
Abstract data container.
Definition: GeometricalInfo.cpp:141
virtual void multiply(const DataContainer &x, const DataContainer &y)
*this = the elementwise product x*y
Definition: stir_data_containers.h:278
virtual float norm() const
returns the norm of this container viewed as a vector
Definition: stir_data_containers.cpp:37
virtual void dot(const DataContainer &a_x, void *ptr) const
calculates the dot product of this container with another one
Definition: stir_data_containers.h:701
Definition: DataHandle.h:159
STIR ProjDataInterfile wrapper with additional file managing features.
Definition: stir_data_containers.h:87
virtual void set_up_geom_info()
Populate the geometrical info metadata (from the image&#39;s own metadata)
Definition: stir_data_containers.cpp:623
Definition: stir_data_containers.h:60
std::shared_ptr< PETAcquisitionData > single_slice_rebinned_data(const int num_segments_to_combine, const int num_views_to_combine=1, const int num_tang_poss_to_trim=0, const bool do_normalisation=true, const int max_in_segment_num_to_process=-1, const int num_tof_bins_to_combine=1)
rebin the data to lower resolution by adding
Definition: stir_data_containers.h:180
virtual void divide(const DataContainer &x, const DataContainer &y)
*this = the elementwise ratio x/y
Definition: stir_data_containers.h:742
virtual float norm() const
returns the norm of this container viewed as a vector
Definition: stir_data_containers.h:687
Definition: stir_data_containers.h:838
virtual void divide(const DataContainer &x, const DataContainer &y)
*this = the elementwise ratio x/y
Definition: stir_data_containers.h:282
Definition: DataContainer.h:41
virtual void fill(const float v)
fill with single value
Definition: stir_data_containers.h:633
Execution status type and wrappers for C++ objects.
virtual void maximum(const DataContainer &x, const DataContainer &y)
*this = the elementwise max(x, y)
Definition: stir_data_containers.h:997
int get_num_sinograms() const
total number of (2D) sinograms
Definition: stir_data_containers.h:314
virtual void divide(const DataContainer &x, const DataContainer &y)
*this = the elementwise ratio x/y
Definition: stir_data_containers.h:993
virtual void maximum(const DataContainer &x, const DataContainer &y)
*this = the elementwise max(x, y)
Definition: stir_data_containers.h:286
STIR ProjData wrapper with added functionality.
Definition: stir_data_containers.h:148
virtual void fill(const PETAcquisitionData &ad)
fill from another PETAcquisitionData
Definition: stir_data_containers.h:646
virtual void copy_to(float *d) const
Copy to float array.
Definition: stir_data_containers.h:675
virtual void minimum(const DataContainer &x, const DataContainer &y)
*this = the elementwise min(x, y)
Definition: stir_data_containers.h:1001
PETAcquisitionDataInMemory(const char *filename)
Constructor for PETAcquisitionDataInMemory from filename.
Definition: stir_data_containers.h:577
virtual void multiply(const DataContainer &x, const DataContainer &y)
*this = the elementwise product x*y
Definition: stir_data_containers.h:721