SIRF  3.4.0
stir_x.h
Go to the documentation of this file.
1 /*
2 SyneRBI Synergistic Image Reconstruction Framework (SIRF)
3 Copyright 2015 - 2021 Rutherford Appleton Laboratory STFC
4 Copyright 2019 - 2021 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 
22 #ifndef EXTRA_STIR_TYPES
23 #define EXTRA_STIR_TYPES
24 
25 #define WIN32_LEAN_AND_MEAN
26 
36 #include <cmath>
37 #include <stdlib.h>
38 
39 #include "sirf/common/iequals.h"
40 #include "sirf/common/JacobiCG.h"
42 #include "stir/recon_buildblock/PoissonLogLikelihoodWithLinearModelForMeanAndProjData.h"
43 
44 #define MIN_BIN_EFFICIENCY 1.0e-20f
45 //#define MIN_BIN_EFFICIENCY 1.0e-6f
46 #define SIRF_DYNAMIC_CAST(T, X, Y) T& X = dynamic_cast<T&>(Y)
47 
48 namespace sirf {
49 
83  class ListmodeToSinograms : public stir::LmToProjData {
84  public:
86 
95  //ListmodeToSinograms(const char* const par) : stir::LmToProjData(par) {}
96  ListmodeToSinograms(const char* par) : stir::LmToProjData(par) {}
97  ListmodeToSinograms() : stir::LmToProjData()
98  {
99  set_defaults();
100  fan_size = -1;
101  store_prompts = true;
102  store_delayeds = false;
103  delayed_increment = 0;
104  num_iterations = 10;
105  display_interval = 1;
106  KL_interval = 1;
107  save_interval = -1;
108  //num_events_to_store = -1;
109  }
110  void set_input(std::string lm_file)
111  {
112  input_filename = lm_file;
113  lm_data_ptr = stir::read_from_file<ListModeData>(input_filename);
114  exam_info_sptr_.reset(new ExamInfo(lm_data_ptr->get_exam_info()));
115  proj_data_info_sptr_.reset(lm_data_ptr->get_proj_data_info_sptr()->clone());
116  }
118 
120  void set_output(std::string proj_data_file)
121  {
122  output_filename_prefix = proj_data_file;
123  }
124  void set_template(std::string proj_data_file)
125  {
126  PETAcquisitionDataInFile acq_data_template(proj_data_file.c_str());
127  set_template(acq_data_template);
128  }
129  void set_template(const PETAcquisitionData& acq_data_template)
130  {
131  template_proj_data_info_ptr =
132  acq_data_template.get_proj_data_info_sptr()->create_shared_clone();
133  }
134  void set_time_interval(double start, double stop)
135  {
136  std::pair<double, double> interval(start, stop);
137  std::vector < std::pair<double, double> > intervals;
138  intervals.push_back(interval);
139  frame_defs = stir::TimeFrameDefinitions(intervals);
140  do_time_frame = true;
141  }
142  int set_flag(const char* flag, bool value)
143  {
144  if (sirf::iequals(flag, "store_prompts"))
145  store_prompts = value;
146  else if (sirf::iequals(flag, "store_delayeds"))
147  store_delayeds = value;
148 #if 0
149  else if (sirf::iequals(flag, "do_pre_normalisation"))
150  do_pre_normalisation = value;
151  else if (sirf::iequals(flag, "do_time_frame"))
152  do_time_frame = value;
153 #endif
154  else if (sirf::iequals(flag, "interactive"))
155  interactive = value;
156  else
157  return -1;
158  return 0;
159  }
160  bool get_store_prompts() const
161  {
162  return store_prompts;
163  }
164  bool get_store_delayeds() const
165  {
166  return store_delayeds;
167  }
168  virtual stir::Succeeded set_up()
169  {
170  if (LmToProjData::set_up() == Succeeded::no)
171  THROW("LmToProjData setup failed");
172  fan_size = -1;
173  const int max_fan_size =
174  lm_data_ptr->get_scanner_ptr()->get_max_num_non_arccorrected_bins();
175  if (fan_size == -1)
176  fan_size = max_fan_size;
177  else
178  fan_size =
179  std::min(fan_size, max_fan_size);
180  half_fan_size = fan_size / 2;
181  fan_size = 2 * half_fan_size + 1;
182 
183  exam_info_sptr_->set_time_frame_definitions(frame_defs);
184  const float h = proj_data_info_sptr_->get_bed_position_horizontal();
185  const float v = proj_data_info_sptr_->get_bed_position_vertical();
186  stir::shared_ptr<ProjDataInfo> temp_proj_data_info_sptr(template_proj_data_info_ptr->clone());
187  temp_proj_data_info_sptr->set_bed_position_horizontal(h);
188  temp_proj_data_info_sptr->set_bed_position_vertical(v);
189  randoms_sptr.reset(new PETAcquisitionDataInMemory(exam_info_sptr_, temp_proj_data_info_sptr));
190 
191  return stir::Succeeded::yes;
192  }
193  int estimate_randoms();
194  void save_randoms()
195  {
196  std::string filename = output_filename_prefix + "_randoms" + "_f1g1d0b0.hs";
197  randoms_sptr->write(filename.c_str());
198  }
199  std::shared_ptr<PETAcquisitionData> get_output()
200  {
201  std::string filename = output_filename_prefix + "_f1g1d0b0.hs";
202  return std::shared_ptr<PETAcquisitionData>
203  (new PETAcquisitionDataInFile(filename.c_str()));
204  }
205  std::shared_ptr<PETAcquisitionData> get_randoms_sptr()
206  {
207  return randoms_sptr;
208  }
211  float get_time_at_which_num_prompts_exceeds_threshold(const unsigned long threshold) const;
212 
213  protected:
214  // variables for ML estimation of singles/randoms
215  int fan_size;
216  int half_fan_size;
217  int max_ring_diff_for_fansums;
218  int num_iterations;
219  int display_interval;
220  int KL_interval;
221  int save_interval;
222  stir::shared_ptr<ExamInfo> exam_info_sptr_;
223  stir::shared_ptr<ProjDataInfo> proj_data_info_sptr_;
224  stir::shared_ptr<std::vector<stir::Array<2, float> > > fan_sums_sptr;
225  stir::shared_ptr<stir::DetectorEfficiencies> det_eff_sptr;
226  std::shared_ptr<PETAcquisitionData> randoms_sptr;
227  void compute_fan_sums_(bool prompt_fansum = false);
228  int compute_singles_();
229 // void estimate_randoms_();
230  static unsigned long compute_num_bins_(const int num_rings,
231  const int num_detectors_per_ring,
232  const int max_ring_diff, const int half_fan_size);
233  };
234 
242  public:
244  // create from bin (detector pair) efficiencies sinograms
246  // create from ECAT8
247  PETAcquisitionSensitivityModel(std::string filename);
248  // chain two normalizations
251  {
252  norm_.reset(new stir::ChainedBinNormalisation(mod1.data(), mod2.data()));
253  }
254 
255  void set_up(const stir::shared_ptr<const stir::ExamInfo>& exam_info_sptr,
256  const stir::shared_ptr<stir::ProjDataInfo>&);
257 
258  // multiply by bin efficiencies
259  virtual void unnormalise(PETAcquisitionData& ad) const;
260  // divide by bin efficiencies
261  virtual void normalise(PETAcquisitionData& ad) const;
262  // same as apply, but returns new data rather than changes old one
263  std::shared_ptr<PETAcquisitionData> forward(const PETAcquisitionData& ad) const
264  {
265  std::shared_ptr<PETAcquisitionData> sptr_ad = ad.new_acquisition_data();
266  sptr_ad->fill(ad);
267  this->unnormalise(*sptr_ad);
268  return sptr_ad;
269  }
270  // same as undo, but returns new data rather than changes old one
271  std::shared_ptr<PETAcquisitionData> invert(const PETAcquisitionData& ad) const
272  {
273  std::shared_ptr<PETAcquisitionData> sptr_ad = ad.new_acquisition_data();
274  sptr_ad->fill(ad);
275  this->normalise(*sptr_ad);
276  return sptr_ad;
277  }
278 
279  stir::shared_ptr<stir::BinNormalisation> data()
280  {
281  return norm_;
282  //return std::dynamic_pointer_cast<stir::BinNormalisation>(norm_);
283  }
284 
285  protected:
286  stir::shared_ptr<stir::BinNormalisation> norm_;
287  //shared_ptr<stir::ChainedBinNormalisation> norm_;
288  };
289 
290 
297  typedef DataProcessor3DF ImageDataProcessor;
298 
345  public:
353  class BFOperator : public Operator<STIRImageData> {
354  public:
355  BFOperator(const PETAcquisitionModel& am) : sptr_am_(am.linear_acq_mod_sptr()) {}
356  void set_subset(int sub_num)
357  {
358  sub_num_ = sub_num;
359  }
360  void set_num_subsets(int num_sub)
361  {
362  num_sub_ = num_sub;
363  }
364  virtual std::shared_ptr<STIRImageData> apply(STIRImageData& image_data)
365  {
366  std::shared_ptr<PETAcquisitionData> sptr_fwd =
367  sptr_am_->forward(image_data, sub_num_, num_sub_); // , true);
368  std::shared_ptr<STIRImageData> sptr_bwd =
369  sptr_am_->backward(*sptr_fwd, sub_num_, num_sub_);
370  return sptr_bwd;
371  }
372  private:
373  std::shared_ptr<const PETAcquisitionModel> sptr_am_;
374  int sub_num_ = 0;
375  int num_sub_ = 1;
376  };
377 
386  float norm(int subset_num = 0, int num_subsets = 1, int num_iter = 2, int verb = 0) const
387  {
388  BFOperator bf(*this);
389  bf.set_subset(subset_num);
390  bf.set_num_subsets(num_subsets);
391  JacobiCG<float> jcg;
392  jcg.set_num_iterations(num_iter);
393  STIRImageData image_data = *sptr_image_template_->clone();
394  image_data.fill(1.0);
395  float lmd = jcg.largest(bf, image_data, verb);
396  return std::sqrt(lmd);
397  }
398 
399  void set_projectors(stir::shared_ptr<stir::ProjectorByBinPair> sptr_projectors)
400  {
401  sptr_projectors_ = sptr_projectors;
402  }
403  const stir::shared_ptr<stir::ProjectorByBinPair> projectors_sptr() const
404  {
405  return sptr_projectors_;
406  }
407  void set_additive_term(std::shared_ptr<PETAcquisitionData> sptr)
408  {
409  sptr_add_ = sptr;
410  }
411  std::shared_ptr<const PETAcquisitionData> additive_term_sptr() const
412  {
413  return sptr_add_;
414  }
415  void set_background_term(std::shared_ptr<PETAcquisitionData> sptr)
416  {
417  sptr_background_ = sptr;
418  }
419  std::shared_ptr<const PETAcquisitionData> background_term_sptr() const
420  {
421  return sptr_background_;
422  }
423  std::shared_ptr<const PETAcquisitionData> acq_template_sptr() const
424  {
425  return sptr_acq_template_;
426  }
427  std::shared_ptr<const STIRImageData> image_template_sptr() const
428  {
429  return sptr_image_template_;
430  }
431  //void set_normalisation(shared_ptr<stir::BinNormalisation> sptr)
432  //{
433  // sptr_normalisation_ = sptr;
434  //}
435  const stir::shared_ptr<stir::BinNormalisation> normalisation_sptr() const
436  {
437  if (sptr_asm_.get())
438  return sptr_asm_->data();
439  stir::shared_ptr<stir::BinNormalisation> sptr;
440  return sptr;
441  //return sptr_normalisation_;
442  }
443  //void set_bin_efficiency(shared_ptr<PETAcquisitionData> sptr_data);
444  //void set_normalisation(shared_ptr<PETAcquisitionData> sptr_data)
445  //{
446  // sptr_normalisation_.reset(new stir::BinNormalisationFromProjData(*sptr_data));
447  //}
448  void set_asm(std::shared_ptr<PETAcquisitionSensitivityModel> sptr_asm)
449  {
450  //sptr_normalisation_ = sptr_asm->data();
451  sptr_asm_ = sptr_asm;
452  }
453  stir::shared_ptr<PETAcquisitionSensitivityModel> asm_sptr() const
454  {
455  return sptr_asm_;
456  }
457 
459 
461  void set_image_data_processor(stir::shared_ptr<ImageDataProcessor> sptr_processor);
462  void cancel_background_term()
463  {
464  sptr_background_.reset();
465  }
466  void cancel_additive_term()
467  {
468  sptr_add_.reset();
469  }
470  void cancel_normalisation()
471  {
472  sptr_asm_.reset();
473  //sptr_normalisation_.reset();
474  }
475  std::shared_ptr<const PETAcquisitionModel> linear_acq_mod_sptr() const
476  {
477  std::shared_ptr<PETAcquisitionModel> sptr_am(new PETAcquisitionModel);
478  sptr_am->set_projectors(sptr_projectors_);
479  sptr_am->set_asm(sptr_asm_);
480  sptr_am->sptr_acq_template_ = sptr_acq_template_;
481  sptr_am->sptr_image_template_ = sptr_image_template_;
482  return sptr_am;
483  }
484 
485  virtual void set_up(
486  std::shared_ptr<PETAcquisitionData> sptr_acq,
487  std::shared_ptr<STIRImageData> sptr_image);
488 
492  std::shared_ptr<PETAcquisitionData>
493  forward(const STIRImageData& image,
494  int subset_num = 0, int num_subsets = 1, bool do_linear_only = false) const;
505  void forward(PETAcquisitionData& acq_data, const STIRImageData& image,
506  int subset_num, int num_subsets, bool zero = false, bool do_linear_only = false) const;
507 
508  // computes and returns back-projected subset of acquisition data
509  std::shared_ptr<STIRImageData> backward(PETAcquisitionData& ad,
510  int subset_num = 0, int num_subsets = 1) const;
511  // puts back-projected subset of acquisition data into image
512  void backward(STIRImageData& image, PETAcquisitionData& ad,
513  int subset_num = 0, int num_subsets = 1) const;
514 
515  protected:
516  stir::shared_ptr<stir::ProjectorByBinPair> sptr_projectors_;
517  std::shared_ptr<PETAcquisitionData> sptr_acq_template_;
518  std::shared_ptr<STIRImageData> sptr_image_template_;
519  std::shared_ptr<PETAcquisitionData> sptr_add_;
520  std::shared_ptr<PETAcquisitionData> sptr_background_;
521  std::shared_ptr<PETAcquisitionSensitivityModel> sptr_asm_;
522  //shared_ptr<stir::BinNormalisation> sptr_normalisation_;
523  };
524 
537  class PETSingleScatterSimulator : public stir::SingleScatterSimulation
538  {
539  public:
541  PETSingleScatterSimulator() : stir::SingleScatterSimulation()
542  {}
544  PETSingleScatterSimulator(std::string filename) :
545  stir::SingleScatterSimulation(filename)
546  {}
547 
548  void set_up(std::shared_ptr<const PETAcquisitionData> sptr_acq_template,
549  std::shared_ptr<const STIRImageData> sptr_act_image_template)
550  {
551  this->sptr_acq_template_ = sptr_acq_template;
552 
553  stir::SingleScatterSimulation::set_template_proj_data_info(
554  *sptr_acq_template_->get_proj_data_info_sptr());
555  stir::SingleScatterSimulation::set_exam_info(
556  *sptr_acq_template_->get_exam_info_sptr());
557  // check if attenuation image is set
558  try
559  {
560  auto& tmp = stir::SingleScatterSimulation::get_attenuation_image();
561  }
562  catch (...)
563  {
564  THROW("Fatal error in PETSingleScatterSimulator::set_up: attenuation_image has not been set");
565  }
566  this->set_activity_image_sptr(sptr_act_image_template);
567 
568  if (stir::SingleScatterSimulation::set_up() == Succeeded::no)
569  THROW("Fatal error in PETSingleScatterSimulator::set_up() failed.");
570  }
571 
572  void set_activity_image_sptr(std::shared_ptr<const STIRImageData> arg)
573  {
574 #if STIR_VERSION < 050000
575  // need to make a copy as the function doesn't accept a const
576  stir::shared_ptr<Image3DF> sptr_image_copy(arg->data_sptr()->clone());
577  stir::SingleScatterSimulation::set_activity_image_sptr(sptr_image_copy);
578 #else
579  stir::SingleScatterSimulation::set_activity_image_sptr(arg->data_sptr());
580 #endif
581  }
582 
583  void set_attenuation_image_sptr(std::shared_ptr<const STIRImageData> arg)
584  {
585 #if STIR_VERSION < 050000
586  // need to make a copy as the function doesn't accept a const
587  stir::shared_ptr<Image3DF> sptr_image_copy(arg->data_sptr()->clone());
588  stir::SingleScatterSimulation::set_density_image_sptr(sptr_image_copy);
589 #else
590  stir::SingleScatterSimulation::set_density_image_sptr(arg->data_sptr());
591 #endif
592  }
593 
594  std::shared_ptr<PETAcquisitionData> forward(const STIRImageData& activity_img) /*TODO CONST*/
595  {
596  if (!sptr_acq_template_.get())
597  THROW("Fatal error in PETSingleScatterSimulator::forward: acquisition template not set");
598  std::shared_ptr<PETAcquisitionData> sptr_ad =
599  sptr_acq_template_->new_acquisition_data();
600  this->forward( *sptr_ad, activity_img);
601  return sptr_ad;
602  }
603 
604  void forward(PETAcquisitionData& ad, const STIRImageData& activity_img) /* TODO CONST*/
605  {
606  stir::shared_ptr<ProjData> sptr_fd = ad.data();
607  this->set_output_proj_data_sptr(sptr_fd);
608  // hopefully STIR checks if template consistent with input data
609  this->process_data();
610  }
611 
612  protected:
613  std::shared_ptr<const PETAcquisitionData> sptr_acq_template_;
614 
615  };
616 
629  class PETScatterEstimator : private stir::ScatterEstimation
630  {
631  public:
633  PETScatterEstimator() : stir::ScatterEstimation()
634  {
635  stir::shared_ptr<stir::PoissonLogLikelihoodWithLinearModelForMeanAndProjData<DiscretisedDensity<3,float> > >
636  obj_sptr(new PoissonLogLikelihoodWithLinearModelForMeanAndProjData<DiscretisedDensity<3,float> >);
637  stir::shared_ptr<stir::OSMAPOSLReconstruction<DiscretisedDensity<3,float> > >
638  recon_sptr(new stir::OSMAPOSLReconstruction<DiscretisedDensity<3,float> >);
639  recon_sptr->set_num_subiterations(8);
640  recon_sptr->set_num_subsets(7); // this works for the mMR. TODO
641  recon_sptr->set_disable_output(true);
642  recon_sptr->set_objective_function_sptr(obj_sptr);
643  stir::shared_ptr<stir::SeparableGaussianImageFilter<float> >
644  filter_sptr(new stir::SeparableGaussianImageFilter<float>);
645  filter_sptr->set_fwhms(stir::make_coordinate(15.F,15.F,15.F));
646  recon_sptr->set_post_processor_sptr(filter_sptr);
647  stir::ScatterEstimation::set_reconstruction_method_sptr(recon_sptr);
648  }
650  PETScatterEstimator(std::string filename) :
651  stir::ScatterEstimation(filename)
652  {}
653 
655  void set_input_sptr(std::shared_ptr<const PETAcquisitionData> arg)
656  {
657  stir::ScatterEstimation::set_input_proj_data_sptr(arg->data());
658  }
660  void set_attenuation_correction_factors_sptr(std::shared_ptr<const PETAcquisitionData> arg)
661  {
662  stir::ScatterEstimation::set_attenuation_correction_proj_data_sptr(arg->data());
663  }
665  void set_asm(std::shared_ptr<PETAcquisitionSensitivityModel> arg)
666  {
667  stir::ScatterEstimation::set_normalisation_sptr(arg->data());
668  }
670  void set_background_sptr(std::shared_ptr<const PETAcquisitionData> arg)
671  {
672  stir::ScatterEstimation::set_background_proj_data_sptr(arg->data());
673  }
674 
675  void set_attenuation_image_sptr(std::shared_ptr<const STIRImageData> arg)
676  {
677 #if STIR_VERSION < 050000
678  // need to make a copy as the function doesn't accept a const
679  stir::shared_ptr<Image3DF> sptr_image_copy(arg->data_sptr()->clone());
680  stir::ScatterEstimation::set_attenuation_image_sptr(sptr_image_copy);
681 #else
682  stir::ScatterEstimation::set_attenuation_image_sptr(arg->data_sptr());
683 #endif
684  }
685 
687 
693  void set_output_prefix(std::string prefix)
694  {
695  stir::ScatterEstimation::set_export_scatter_estimates_of_each_iteration(!prefix.empty());
696  stir::ScatterEstimation::set_output_scatter_estimate_prefix(prefix);
697  }
698 
699  void set_num_iterations(int arg)
700  {
701  stir::ScatterEstimation::set_num_iterations(arg);
702  }
703 
704  int get_num_iterations() const
705  {
706  return stir::ScatterEstimation::get_num_iterations();
707  }
708 
709  std::shared_ptr<PETAcquisitionData> get_scatter_estimate(int est_num = -1) const
710  {
711  if (est_num == -1) // Get the last one
712  est_num = num_scatter_iterations;
713  if (est_num == num_scatter_iterations)
714  return get_output();
715  // try to read from file
716  if (output_scatter_estimate_prefix.empty())
717  THROW("output_scatter_estimate_prefix not set, so scatter estimates were not saved to file.");
718  const std::string filename = output_scatter_estimate_prefix + "_" + std::to_string(est_num) + ".hs";
719  return std::make_shared<PETAcquisitionDataInFile>(filename.c_str());
720  }
721 
723  std::shared_ptr<PETAcquisitionData> get_output() const
724  {
725  auto stir_proj_data_sptr = stir::ScatterEstimation::get_output();
726  if (!stir_proj_data_sptr)
727  THROW("output not yet computed");
728  std::shared_ptr<PETAcquisitionData> sptr_acq_data
729  (PETAcquisitionData::storage_template()->same_acquisition_data(stir_proj_data_sptr->get_exam_info_sptr(),
730  stir_proj_data_sptr->get_proj_data_info_sptr()->create_shared_clone()));
731  sptr_acq_data->data()->fill(*stir_proj_data_sptr);
732  return sptr_acq_data;
733  }
734 
736 
742  Succeeded set_up()
743  {
744  // reconstruct an smooth image with a large voxel size
745  const float zoom = 0.2F;
746  stir::shared_ptr<Voxels3DF>
747  image_sptr(new Voxels3DF(MAKE_SHARED<stir::ExamInfo>(*this->get_input_data()->get_exam_info_sptr()),
748  *this->get_input_data()->get_proj_data_info_sptr(),
749  zoom));
750  image_sptr->fill(1.F);
751  stir::ScatterEstimation::set_initial_activity_image_sptr(image_sptr);
752  if (stir::ScatterEstimation::set_up() == Succeeded::no)
753  THROW("scatter estimation set_up failed");
754  return Succeeded::yes;
755  }
756  void process()
757  {
758  if (!stir::ScatterEstimation::already_setup())
759  THROW("scatter estimation needs to be set-up first");
760  if (stir::ScatterEstimation::process_data() == Succeeded::no)
761  THROW("scatter estimation failed");
762  }
763  };
764 
780  public:
782  {
783  this->sptr_projectors_.reset(new ProjectorPairUsingMatrix);
784  }
785  void set_matrix(stir::shared_ptr<stir::ProjMatrixByBin> sptr_matrix)
786  {
787  sptr_matrix_ = sptr_matrix;
788  ((ProjectorPairUsingMatrix*)this->sptr_projectors_.get())->
789  set_proj_matrix_sptr(sptr_matrix);
790  }
791  stir::shared_ptr<stir::ProjMatrixByBin> matrix_sptr()
792  {
793  return sptr_matrix_;
794  //return ((ProjectorPairUsingMatrix*)this->sptr_projectors_.get())->
795  // get_proj_matrix_sptr();
796  }
797  virtual void set_up(
798  std::shared_ptr<PETAcquisitionData> sptr_acq,
799  std::shared_ptr<STIRImageData> sptr_image)
800  {
801  if (!sptr_matrix_.get())
802  THROW("PETAcquisitionModelUsingMatrix setup failed - matrix not set");
803  PETAcquisitionModel::set_up(sptr_acq, sptr_image);
804  }
805 
807  void enable_cache(bool v = true)
808  {
809  sptr_matrix_->enable_cache(v);
810  }
811 
812  private:
813  stir::shared_ptr<stir::ProjMatrixByBin> sptr_matrix_;
814  };
815 
818  public:
819  PETAcquisitionModelUsingRayTracingMatrix(int num_LORs = 2) :
821  {
822  stir::shared_ptr<RayTracingMatrix> matrix_sptr(new RayTracingMatrix);
823  matrix_sptr->set_num_tangential_LORs(num_LORs);
824  set_matrix(matrix_sptr);
825  }
826  void set_num_tangential_LORs(int num_LORs)
827  {
828  //RayTracingMatrix& matrix = (RayTracingMatrix&)*matrix_sptr();
829  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
830  //std::cout << matrix.get_num_tangential_LORs() << '\n';
831  matrix.set_num_tangential_LORs(num_LORs);
832  //std::cout << get_num_tangential_LORs() << '\n';
833  }
836  {
837  auto matrix = dynamic_cast<const RayTracingMatrix&>(*matrix_sptr());
838  return matrix.get_num_tangential_LORs();
839  }
842  {
843  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
844  matrix.set_restrict_to_cylindrical_FOV(v);
845  }
848  //bool get_do_symmetry_90degrees_min_phi() const;
849  void set_do_symmetry_90degrees_min_phi(bool v = true)
850  {
851  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
852  matrix.set_do_symmetry_90degrees_min_phi(v);
853  }
854  //bool get_do_symmetry_180degrees_min_phi() const;
855  void set_do_symmetry_180degrees_min_phi(bool v = true)
856  {
857  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
858  matrix.set_do_symmetry_180degrees_min_phi(v);
859  }
860  //bool get_do_symmetry_swap_segment() const;
861  void set_do_symmetry_swap_segment(bool v = true)
862  {
863  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
864  matrix.set_do_symmetry_swap_segment(v);
865  }
866  //bool get_do_symmetry_swap_s() const;
867  void set_do_symmetry_swap_s(bool v = true)
868  {
869  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
870  matrix.set_do_symmetry_swap_s(v);
871  }
872  //bool get_do_symmetry_shift_z() const;
873  void set_do_symmetry_shift_z(bool v = true)
874  {
875  auto matrix = dynamic_cast<RayTracingMatrix&>(*matrix_sptr());
876  matrix.set_do_symmetry_shift_z(v);
877  }
878  };
879 
882  typedef std::shared_ptr<AcqMod3DF> sptrAcqMod3DF;
883 
884 #ifdef STIR_WITH_NiftyPET_PROJECTOR
885 
890  class PETAcquisitionModelUsingNiftyPET : public PETAcquisitionModel {
891  public:
892  PETAcquisitionModelUsingNiftyPET()
893  {
894  _NiftyPET_projector_pair_sptr.reset(new ProjectorPairUsingNiftyPET);
895  this->sptr_projectors_ = _NiftyPET_projector_pair_sptr;
896  // Set verbosity to 0 by default
897  _NiftyPET_projector_pair_sptr->set_verbosity(0);
898  }
899  void set_cuda_verbosity(const bool verbosity) const
900  {
901  _NiftyPET_projector_pair_sptr->set_verbosity(verbosity);
902  }
903  void set_use_truncation(const bool use_truncation) const
904  {
905  _NiftyPET_projector_pair_sptr->set_use_truncation(use_truncation);
906  }
907  protected:
908  stir::shared_ptr<stir::ProjectorPairUsingNiftyPET> _NiftyPET_projector_pair_sptr;
909  };
910  typedef PETAcquisitionModelUsingNiftyPET AcqModUsingNiftyPET3DF;
911 #endif
912 
913 #ifdef STIR_WITH_Parallelproj_PROJECTOR
914 
919  class PETAcquisitionModelUsingParallelproj : public PETAcquisitionModel {
920  public:
921  PETAcquisitionModelUsingParallelproj()
922  {
923  this->sptr_projectors_.reset(new ProjectorByBinPairUsingParallelproj);
924  }
925  };
926  typedef PETAcquisitionModelUsingParallelproj AcqModUsingParallelproj;
927 #endif
928 
936  public:
938  // multiply by bin efficiencies
939  virtual void unnormalise(PETAcquisitionData& ad) const;
940  // divide by bin efficiencies
941  virtual void normalise(PETAcquisitionData& ad) const;
942  protected:
943  stir::shared_ptr<stir::ForwardProjectorByBin> sptr_forw_projector_;
944  };
945 
955  class xSTIR_GeneralisedPrior3DF : public stir::GeneralisedPrior < Image3DF > {
956  public:
957 // bool post_process() {
958 // return post_processing();
959 // }
960  };
961 
962  class xSTIR_QuadraticPrior3DF : public stir::QuadraticPrior < float > {
963  public:
964  void only2D(int only) {
965  only_2D = only != 0;
966  }
967  };
968 
969  class xSTIR_PLSPrior3DF : public stir::PLSPrior < float > {
970  public:
971  void only2D(int only) {
972  only_2D = only != 0;
973  }
974  };
975 
977  public stir::GeneralisedObjectiveFunction < Image3DF > {
978  public:
979 // bool post_process() {
980 // return post_processing();
981 // }
982  };
983 
984  //typedef xSTIR_GeneralisedObjectiveFunction3DF ObjectiveFunction3DF;
985 
987  public stir::PoissonLogLikelihoodWithLinearModelForMeanAndProjData < Image3DF > {
988  public:
989  void set_input_file(const char* filename) {
990  input_filename = filename;
991  }
992  void set_acquisition_data(std::shared_ptr<PETAcquisitionData> sptr)
993  {
994  sptr_ad_ = sptr;
995  set_proj_data_sptr(sptr->data());
996  }
997  void set_acquisition_model(std::shared_ptr<AcqMod3DF> sptr_am)
998  {
999  sptr_am_ = sptr_am;
1000  AcqMod3DF& am = *sptr_am;
1001  auto sptr_asm = am.asm_sptr();
1002  set_projector_pair_sptr(am.projectors_sptr());
1003  bool have_a = am.additive_term_sptr().get();
1004  bool have_b = am.background_term_sptr().get();
1005  bool have_asm = sptr_asm.get();
1006  if (!have_b) {
1007  if (have_a)
1008  set_additive_proj_data_sptr(am.additive_term_sptr()->data());
1009  }
1010  else {
1011  auto sptr_b = am.background_term_sptr();
1012  stir::shared_ptr<PETAcquisitionData> sptr;
1013  if (have_asm)
1014  sptr = sptr_asm->invert(*sptr_b);
1015  else
1016  sptr = sptr_b->clone();
1017  if (have_a) {
1018  auto sptr_a = am.additive_term_sptr();
1019  float a = 1.0f;
1020  sptr->axpby(&a, *sptr, &a, *sptr_a);
1021  }
1022  set_additive_proj_data_sptr(sptr->data());
1023  }
1024  if (am.normalisation_sptr().get())
1025  set_normalisation_sptr(am.normalisation_sptr());
1026  }
1027  std::shared_ptr<AcqMod3DF> acquisition_model_sptr()
1028  {
1029  return sptr_am_;
1030  }
1031  private:
1032  std::shared_ptr<PETAcquisitionData> sptr_ad_;
1033  std::shared_ptr<AcqMod3DF> sptr_am_;
1034  };
1035 
1038 
1040  public stir::IterativeReconstruction < Image3DF > {
1041  public:
1042 /* bool post_process() {
1043  //std::cout << "in xSTIR_IterativeReconstruction3DF.post_process...\n";
1044  if (this->output_filename_prefix.length() < 1)
1045  this->set_output_filename_prefix("reconstructed_image");
1046  return post_processing();
1047  }*/
1048  void update(Image3DF &image) {
1049  update_estimate(image);
1050  end_of_iteration_processing(image);
1051  subiteration_num++;
1052  }
1053  void update(STIRImageData& id)
1054  {
1055  update(id.data());
1056  }
1057  void update(stir::shared_ptr<STIRImageData> sptr_id)
1058  {
1059  update(*sptr_id);
1060  }
1061  int& subiteration() {
1062  return subiteration_num;
1063  }
1064  int subiteration() const {
1065  return subiteration_num;
1066  }
1067  void set_initial_estimate_file(const char* filename) {
1068  initial_data_filename = filename;
1069  }
1070  };
1071 
1072  class xSTIR_OSMAPOSLReconstruction3DF : public stir::OSMAPOSLReconstruction< Image3DF > {
1073  public:
1074  int& subiteration() {
1075  return subiteration_num;
1076  }
1077  int subiteration() const {
1078  return subiteration_num;
1079  }
1080  };
1081 
1082  class xSTIR_OSSPSReconstruction3DF : public stir::OSSPSReconstruction < Image3DF > {
1083  public:
1084  float& relaxation_parameter_value() {
1085  return relaxation_parameter;
1086  }
1087  };
1088 
1089  class xSTIR_FBP2DReconstruction : public stir::FBP2DReconstruction {
1090  public:
1092  {
1093  _is_set_up = false;
1094  }
1095  void set_input(const PETAcquisitionData& acq)
1096  {
1097  set_input_data(acq.data());
1098  }
1099  void set_zoom(float v)
1100  {
1101  set_zoom_xy(v);
1102  _is_set_up = false;
1103  }
1104  void set_alpha_ramp(double alpha)
1105  {
1106  // does not work!
1107  //assert(alpha > 0 && alpha <= 1.0);
1108  if (!(alpha > 0 && alpha <= 1.0))
1109  throw LocalisedException
1110  ("wrong ramp filter parameter alpha", __FILE__, __LINE__);
1111  alpha_ramp = alpha;
1112  }
1113  void set_frequency_cut_off(double fc)
1114  {
1115  if (!(fc > 0 && fc <= 0.5))
1116  throw LocalisedException
1117  ("wrong frequency cut-off", __FILE__, __LINE__);
1118  fc_ramp = fc;
1119  }
1120  void set_up(std::shared_ptr<STIRImageData> sptr_id)
1121  {
1122  _sptr_image_data.reset(new STIRImageData(*sptr_id));
1123  stir::Succeeded s = stir::Reconstruction<Image3DF>::set_up(_sptr_image_data->data_sptr());
1124  if (s != stir::Succeeded::yes)
1125  THROW("stir::Reconstruction setup failed");
1126  _is_set_up = true;
1127  }
1128  void cancel_setup()
1129  {
1130  _is_set_up = false;
1131  }
1132  void process()
1133  {
1134  stir::Succeeded s = stir::Succeeded::no;
1135  if (!_is_set_up) {
1136  stir::shared_ptr<Image3DF> sptr_image(construct_target_image_ptr());
1137  _sptr_image_data.reset(new STIRImageData(sptr_image));
1138  stir::Reconstruction<Image3DF>::set_up(sptr_image);
1139  s = reconstruct(sptr_image);
1140  }
1141  else
1142  s = reconstruct(_sptr_image_data->data_sptr());
1143  if (s != stir::Succeeded::yes)
1144  THROW("stir::AnalyticReconstruction::reconstruct failed");
1145  }
1146  std::shared_ptr<STIRImageData> get_output()
1147  {
1148  return _sptr_image_data;
1149  }
1150  protected:
1151  bool _is_set_up;
1152  std::shared_ptr<STIRImageData> _sptr_image_data;
1153  };
1154 
1156  public stir::SeparableGaussianImageFilter<float> {
1157  public:
1158  //stir::Succeeded set_up(const STIRImageData& id)
1159  //{
1160  // return virtual_set_up(id.data());
1161  //}
1162  //void apply(STIRImageData& id)
1163  //{
1164  // virtual_apply(id.data());
1165  //}
1166  void set_fwhms_xyz(char xyz, float f)
1167  {
1168  stir::BasicCoordinate<3, float> v = get_fwhms();
1169  switch (xyz) {
1170  case 'z':
1171  v[1] = f;
1172  break;
1173  case 'y':
1174  v[2] = f;
1175  break;
1176  case 'x':
1177  v[3] = f;
1178  }
1179  set_fwhms(v);
1180  }
1181  void set_max_kernel_sizes_xyz(char xyz, int s)
1182  {
1183  stir::BasicCoordinate<3, int> v = get_max_kernel_sizes();
1184  switch (xyz) {
1185  case 'z':
1186  v[1] = s;
1187  break;
1188  case 'y':
1189  v[2] = s;
1190  break;
1191  case 'x':
1192  v[3] = s;
1193  }
1194  set_max_kernel_sizes(v);
1195  }
1196  };
1197 }
1198 
1199 #endif
STIR DiscretisedDensity<3, float> wrapper with added functionality.
Definition: stir_data_containers.h:783
Definition: LocalisedException.h:32
Ray tracing matrix implementation of the PET acquisition model.
Definition: stir_x.h:779
PETSingleScatterSimulator()
Default constructor.
Definition: stir_x.h:541
std::shared_ptr< PETAcquisitionData > get_output() const
get last scatter estimate
Definition: stir_x.h:723
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.
void enable_cache(bool v=true)
Enables or disables the caching mechanism.
Definition: stir_x.h:807
Definition: stir_x.h:1072
int get_num_tangential_LORs()
@
Definition: stir_x.h:835
Succeeded set_up()
set up the object and performs checks
Definition: stir_x.h:742
PETScatterEstimator(std::string filename)
Overloaded constructor which takes the parameter file.
Definition: stir_x.h:650
Definition: stir_x.h:1089
void set_output(std::string proj_data_file)
Specifies the prefix for the output file(s),.
Definition: stir_x.h:120
Definition: Operator.h:7
std::unique_ptr< STIRImageData > clone() const
Clone and return as unique pointer.
Definition: stir_data_containers.h:1094
DataProcessor3DF ImageDataProcessor
A typedef to use SIRF terminology for DataProcessors.
Definition: stir_x.h:297
In-memory implementation of PETAcquisitionData.
Definition: stir_data_containers.h:534
void set_output_prefix(std::string prefix)
Set prefix for filenames with scatter estimates.
Definition: stir_x.h:693
Definition: stir_x.h:962
Accessor classes.
Definition: stir_x.h:955
Class for simulating the scatter contribution to PET data.
Definition: stir_x.h:537
In-file implementation of PETAcquisitionData.
Definition: stir_data_containers.h:420
void set_background_sptr(std::shared_ptr< const PETAcquisitionData > arg)
Set the background data (normally equal to the randoms in PET)
Definition: stir_x.h:670
Specification file for data handling types not present in STIR.
Definition: JacobiCG.h:37
Class for a PET acquisition model.
Definition: stir_x.h:344
Abstract data container.
Definition: GeometricalInfo.cpp:141
Class for the product of backward and forward projectors of a PET acquisition model.
Definition: stir_x.h:353
Class for PET scanner detector efficiencies model.
Definition: stir_x.h:241
void set_attenuation_correction_factors_sptr(std::shared_ptr< const PETAcquisitionData > arg)
Set attenuation correction factors as acq_data.
Definition: stir_x.h:660
PETSingleScatterSimulator(std::string filename)
Overloaded constructor which takes the parameter file.
Definition: stir_x.h:544
void set_asm(std::shared_ptr< PETAcquisitionSensitivityModel > arg)
Set acquisition sensitivity model specifying detection efficiencies (without attenuation) ...
Definition: stir_x.h:665
Definition: stir_x.h:969
ListmodeToSinograms(const char *par)
Constructor.
Definition: stir_x.h:96
float get_time_at_which_num_prompts_exceeds_threshold(const unsigned long threshold) const
Definition: stir_x.cpp:53
Definition: stir_x.h:1082
Class for estimating the scatter contribution in PET projection data.
Definition: stir_x.h:629
Listmode-to-sinograms converter.
Definition: stir_x.h:83
void set_input_sptr(std::shared_ptr< const PETAcquisitionData > arg)
Set the input data.
Definition: stir_x.h:655
Attenuation model.
Definition: stir_x.h:935
void set_restrict_to_cylindrical_FOV(bool v=true)
Enables or disables using a circular axial FOV (vs rectangular)
Definition: stir_x.h:841
STIR ProjData wrapper with added functionality.
Definition: stir_data_containers.h:148
float norm(int subset_num=0, int num_subsets=1, int num_iter=2, int verb=0) const
Method computing the norm of the linear part S G of the PET acquisition model operator F...
Definition: stir_x.h:386