SIRF  3.5.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  STIRAcquisitionDataInFile acq_data_template(proj_data_file.c_str());
127  set_template(acq_data_template);
128  }
129  void set_template(const STIRAcquisitionData& 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 STIRAcquisitionDataInMemory(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<STIRAcquisitionData> get_output()
200  {
201  std::string filename = output_filename_prefix + "_f1g1d0b0.hs";
202  return std::shared_ptr<STIRAcquisitionData>
203  (new STIRAcquisitionDataInFile(filename.c_str()));
204  }
205  std::shared_ptr<STIRAcquisitionData> 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<STIRAcquisitionData> 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(STIRAcquisitionData& ad) const;
260  // divide by bin efficiencies
261  virtual void normalise(STIRAcquisitionData& ad) const;
262  // same as apply, but returns new data rather than changes old one
263  std::shared_ptr<STIRAcquisitionData> forward(const STIRAcquisitionData& ad) const
264  {
265  std::shared_ptr<STIRAcquisitionData> 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<STIRAcquisitionData> invert(const STIRAcquisitionData& ad) const
272  {
273  std::shared_ptr<STIRAcquisitionData> 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(const STIRImageData& image_data)
365  {
366  std::shared_ptr<STIRAcquisitionData> 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<STIRAcquisitionData> sptr)
408  {
409  sptr_add_ = sptr;
410  }
411  std::shared_ptr<const STIRAcquisitionData> additive_term_sptr() const
412  {
413  return sptr_add_;
414  }
415  void set_background_term(std::shared_ptr<STIRAcquisitionData> sptr)
416  {
417  sptr_background_ = sptr;
418  }
419  std::shared_ptr<const STIRAcquisitionData> background_term_sptr() const
420  {
421  return sptr_background_;
422  }
423  std::shared_ptr<const STIRAcquisitionData> 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<STIRAcquisitionData> sptr_data);
444  //void set_normalisation(shared_ptr<STIRAcquisitionData> 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<STIRAcquisitionData> sptr_acq,
487  std::shared_ptr<STIRImageData> sptr_image);
488 
492  std::shared_ptr<STIRAcquisitionData>
493  forward(const STIRImageData& image,
494  int subset_num = 0, int num_subsets = 1, bool do_linear_only = false) const;
505  void forward(STIRAcquisitionData& 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(const STIRAcquisitionData& 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, const STIRAcquisitionData& 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<STIRAcquisitionData> sptr_acq_template_;
518  std::shared_ptr<STIRImageData> sptr_image_template_;
519  std::shared_ptr<STIRAcquisitionData> sptr_add_;
520  std::shared_ptr<STIRAcquisitionData> 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 STIRAcquisitionData> 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<STIRAcquisitionData> 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<STIRAcquisitionData> 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(STIRAcquisitionData& 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 STIRAcquisitionData> 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 STIRAcquisitionData> arg)
656  {
657  stir::ScatterEstimation::set_input_proj_data_sptr(arg->data());
658  }
660  void set_attenuation_correction_factors_sptr(std::shared_ptr<const STIRAcquisitionData> 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 STIRAcquisitionData> 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<STIRAcquisitionData> 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<STIRAcquisitionDataInFile>(filename.c_str());
720  }
721 
723  std::shared_ptr<STIRAcquisitionData> 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<STIRAcquisitionData> sptr_acq_data
729  (STIRAcquisitionData::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<STIRAcquisitionData> 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 
880  typedef PETAcquisitionModel AcqMod3DF;
881  typedef PETAcquisitionModelUsingMatrix AcqModUsingMatrix3DF;
882  typedef std::shared_ptr<AcqMod3DF> sptrAcqMod3DF;
883 
884 #ifdef STIR_WITH_NiftyPET_PROJECTOR
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
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(STIRAcquisitionData& ad) const;
940  // divide by bin efficiencies
941  virtual void normalise(STIRAcquisitionData& ad) const;
942  protected:
943  stir::shared_ptr<stir::ForwardProjectorByBin> sptr_forw_projector_;
944  };
945 
955  class xSTIR_Box3D : public stir::Box3D {
956  public:
957  void set_length_x(float v)
958  {
959  length_x = v;
960  }
961  void set_length_y(float v)
962  {
963  length_y = v;
964  }
965  void set_length_z(float v)
966  {
967  length_z = v;
968  }
969  float get_length_x() const
970  {
971  return length_x;
972  }
973  float get_length_y() const
974  {
975  return length_y;
976  }
977  float get_length_z() const
978  {
979  return length_z;
980  }
981  };
982 
983  class xSTIR_GeneralisedPrior3DF : public stir::GeneralisedPrior < Image3DF > {
984  public:
985 // bool post_process() {
986 // return post_processing();
987 // }
988  };
989 
990  class xSTIR_QuadraticPrior3DF : public stir::QuadraticPrior < float > {
991  public:
992  void only2D(int only) {
993  only_2D = only != 0;
994  }
995  };
996 
997  class xSTIR_LogcoshPrior3DF : public stir::LogcoshPrior < float > {
998  public:
999  void only2D(int only) {
1000  only_2D = only != 0;
1001  }
1002  };
1003 
1004  class xSTIR_RelativeDifferencePrior3DF : public stir::RelativeDifferencePrior < float > {
1005  public:
1006  void only2D(int only) {
1007  only_2D = only != 0;
1008  }
1009  };
1010 
1011  class xSTIR_PLSPrior3DF : public stir::PLSPrior < float > {
1012  public:
1013  void only2D(int only) {
1014  only_2D = only != 0;
1015  }
1016  };
1017 
1019  public stir::GeneralisedObjectiveFunction < Image3DF > {
1020  public:
1021 // bool post_process() {
1022 // return post_processing();
1023 // }
1024  };
1025 
1026  //typedef xSTIR_GeneralisedObjectiveFunction3DF ObjectiveFunction3DF;
1027 
1029  public stir::PoissonLogLikelihoodWithLinearModelForMeanAndProjData < Image3DF > {
1030  public:
1031  void set_input_file(const char* filename) {
1032  input_filename = filename;
1033  }
1034  void set_acquisition_data(std::shared_ptr<STIRAcquisitionData> sptr)
1035  {
1036  sptr_ad_ = sptr;
1037  set_proj_data_sptr(sptr->data());
1038  }
1039  void set_acquisition_model(std::shared_ptr<AcqMod3DF> sptr_am)
1040  {
1041  sptr_am_ = sptr_am;
1042  AcqMod3DF& am = *sptr_am;
1043  auto sptr_asm = am.asm_sptr();
1044  set_projector_pair_sptr(am.projectors_sptr());
1045  bool have_a = am.additive_term_sptr().get();
1046  bool have_b = am.background_term_sptr().get();
1047  bool have_asm = sptr_asm.get();
1048  if (!have_b) {
1049  if (have_a)
1050  set_additive_proj_data_sptr(am.additive_term_sptr()->data());
1051  }
1052  else {
1053  auto sptr_b = am.background_term_sptr();
1054  stir::shared_ptr<STIRAcquisitionData> sptr;
1055  if (have_asm)
1056  sptr = sptr_asm->invert(*sptr_b);
1057  else
1058  sptr = sptr_b->clone();
1059  if (have_a) {
1060  auto sptr_a = am.additive_term_sptr();
1061  float a = 1.0f;
1062  sptr->axpby(&a, *sptr, &a, *sptr_a);
1063  }
1064  set_additive_proj_data_sptr(sptr->data());
1065  }
1066  if (am.normalisation_sptr().get())
1067  set_normalisation_sptr(am.normalisation_sptr());
1068  }
1069  std::shared_ptr<AcqMod3DF> acquisition_model_sptr()
1070  {
1071  return sptr_am_;
1072  }
1073  private:
1074  std::shared_ptr<STIRAcquisitionData> sptr_ad_;
1075  std::shared_ptr<AcqMod3DF> sptr_am_;
1076  };
1077 
1080 
1082  public stir::IterativeReconstruction < Image3DF > {
1083  public:
1084 /* bool post_process() {
1085  //std::cout << "in xSTIR_IterativeReconstruction3DF.post_process...\n";
1086  if (this->output_filename_prefix.length() < 1)
1087  this->set_output_filename_prefix("reconstructed_image");
1088  return post_processing();
1089  }*/
1090  void update(Image3DF &image) {
1091  update_estimate(image);
1092  end_of_iteration_processing(image);
1093  subiteration_num++;
1094  }
1095  void update(STIRImageData& id)
1096  {
1097  update(id.data());
1098  }
1099  void update(stir::shared_ptr<STIRImageData> sptr_id)
1100  {
1101  update(*sptr_id);
1102  }
1103  int& subiteration() {
1104  return subiteration_num;
1105  }
1106  int subiteration() const {
1107  return subiteration_num;
1108  }
1109  void set_initial_estimate_file(const char* filename) {
1110  initial_data_filename = filename;
1111  }
1112  };
1113 
1114  class xSTIR_OSMAPOSLReconstruction3DF : public stir::OSMAPOSLReconstruction< Image3DF > {
1115  public:
1116  int& subiteration() {
1117  return subiteration_num;
1118  }
1119  int subiteration() const {
1120  return subiteration_num;
1121  }
1122  };
1123 
1124  class xSTIR_KOSMAPOSLReconstruction3DF : public stir::KOSMAPOSLReconstruction< Image3DF > {
1125  public:
1126  void compute_kernelised_image_x(
1127  Image3DF& kernelised_image_out,
1128  const Image3DF& image_to_kernelise,
1129  const Image3DF& current_alpha_estimate)
1130  {
1131  compute_kernelised_image(
1132  kernelised_image_out,
1133  image_to_kernelise,
1134  current_alpha_estimate);
1135  }
1136  };
1137 
1138  class xSTIR_OSSPSReconstruction3DF : public stir::OSSPSReconstruction < Image3DF > {
1139  public:
1140  float& relaxation_parameter_value() {
1141  return relaxation_parameter;
1142  }
1143  };
1144 
1145  class xSTIR_FBP2DReconstruction : public stir::FBP2DReconstruction {
1146  public:
1148  {
1149  _is_set_up = false;
1150  }
1151  void set_input(const STIRAcquisitionData& acq)
1152  {
1153  set_input_data(acq.data());
1154  }
1155  void set_zoom(float v)
1156  {
1157  set_zoom_xy(v);
1158  _is_set_up = false;
1159  }
1160  void set_alpha_ramp(double alpha)
1161  {
1162  // does not work!
1163  //assert(alpha > 0 && alpha <= 1.0);
1164  if (!(alpha > 0 && alpha <= 1.0))
1165  throw LocalisedException
1166  ("wrong ramp filter parameter alpha", __FILE__, __LINE__);
1167  alpha_ramp = alpha;
1168  }
1169  void set_frequency_cut_off(double fc)
1170  {
1171  if (!(fc > 0 && fc <= 0.5))
1172  throw LocalisedException
1173  ("wrong frequency cut-off", __FILE__, __LINE__);
1174  fc_ramp = fc;
1175  }
1176  void set_up(std::shared_ptr<STIRImageData> sptr_id)
1177  {
1178  _sptr_image_data.reset(new STIRImageData(*sptr_id));
1179  stir::Succeeded s = stir::Reconstruction<Image3DF>::set_up(_sptr_image_data->data_sptr());
1180  if (s != stir::Succeeded::yes)
1181  THROW("stir::Reconstruction setup failed");
1182  _is_set_up = true;
1183  }
1184  void cancel_setup()
1185  {
1186  _is_set_up = false;
1187  }
1188  void process()
1189  {
1190  stir::Succeeded s = stir::Succeeded::no;
1191  if (!_is_set_up) {
1192  stir::shared_ptr<Image3DF> sptr_image(construct_target_image_ptr());
1193  _sptr_image_data.reset(new STIRImageData(sptr_image));
1194  stir::Reconstruction<Image3DF>::set_up(sptr_image);
1195  s = reconstruct(sptr_image);
1196  }
1197  else
1198  s = reconstruct(_sptr_image_data->data_sptr());
1199  if (s != stir::Succeeded::yes)
1200  THROW("stir::AnalyticReconstruction::reconstruct failed");
1201  }
1202  std::shared_ptr<STIRImageData> get_output()
1203  {
1204  return _sptr_image_data;
1205  }
1206  protected:
1207  bool _is_set_up;
1208  std::shared_ptr<STIRImageData> _sptr_image_data;
1209  };
1210 
1212  public stir::SeparableGaussianImageFilter<float> {
1213  public:
1214  //stir::Succeeded set_up(const STIRImageData& id)
1215  //{
1216  // return virtual_set_up(id.data());
1217  //}
1218  //void apply(STIRImageData& id)
1219  //{
1220  // virtual_apply(id.data());
1221  //}
1222  void set_fwhms_xyz(char xyz, float f)
1223  {
1224  stir::BasicCoordinate<3, float> v = get_fwhms();
1225  switch (xyz) {
1226  case 'z':
1227  v[1] = f;
1228  break;
1229  case 'y':
1230  v[2] = f;
1231  break;
1232  case 'x':
1233  v[3] = f;
1234  }
1235  set_fwhms(v);
1236  }
1237  void set_max_kernel_sizes_xyz(char xyz, int s)
1238  {
1239  stir::BasicCoordinate<3, int> v = get_max_kernel_sizes();
1240  switch (xyz) {
1241  case 'z':
1242  v[1] = s;
1243  break;
1244  case 'y':
1245  v[2] = s;
1246  break;
1247  case 'x':
1248  v[3] = s;
1249  }
1250  set_max_kernel_sizes(v);
1251  }
1252  };
1253 }
1254 
1255 #endif
Definition: LocalisedException.h:32
Definition: JacobiCG.h:37
Listmode-to-sinograms converter.
Definition: stir_x.h:83
void set_output(std::string proj_data_file)
Specifies the prefix for the output file(s),.
Definition: stir_x.h:120
float get_time_at_which_num_prompts_exceeds_threshold(const unsigned long threshold) const
Definition: stir_x.cpp:53
ListmodeToSinograms(const char *par)
Constructor.
Definition: stir_x.h:96
Definition: Operator.h:7
Class for the product of backward and forward projectors of a PET acquisition model.
Definition: stir_x.h:353
Class for a PET acquisition model.
Definition: stir_x.h:344
void set_image_data_processor(stir::shared_ptr< ImageDataProcessor > sptr_processor)
sets data processor to use on the image before forward projection and after back projection
Definition: stir_x.cpp:497
std::shared_ptr< STIRAcquisitionData > forward(const STIRImageData &image, int subset_num=0, int num_subsets=1, bool do_linear_only=false) const
computes and returns a subset of forward-projected data
Definition: stir_x.cpp:545
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
Ray tracing matrix implementation of the PET acquisition model.
Definition: stir_x.h:779
void enable_cache(bool v=true)
Enables or disables the caching mechanism.
Definition: stir_x.h:807
int get_num_tangential_LORs()
@
Definition: stir_x.h:835
void set_restrict_to_cylindrical_FOV(bool v=true)
Enables or disables using a circular axial FOV (vs rectangular)
Definition: stir_x.h:841
Class for PET scanner detector efficiencies model.
Definition: stir_x.h:241
Attenuation model.
Definition: stir_x.h:935
Class for estimating the scatter contribution in PET projection data.
Definition: stir_x.h:630
void set_attenuation_correction_factors_sptr(std::shared_ptr< const STIRAcquisitionData > arg)
Set attenuation correction factors as acq_data.
Definition: stir_x.h:660
void set_input_sptr(std::shared_ptr< const STIRAcquisitionData > arg)
Set the input data.
Definition: stir_x.h:655
std::shared_ptr< STIRAcquisitionData > get_output() const
get last scatter estimate
Definition: stir_x.h:723
void set_background_sptr(std::shared_ptr< const STIRAcquisitionData > arg)
Set the background data (normally equal to the randoms in PET)
Definition: stir_x.h:670
Succeeded set_up()
set up the object and performs checks
Definition: stir_x.h:742
void set_asm(std::shared_ptr< PETAcquisitionSensitivityModel > arg)
Set acquisition sensitivity model specifying detection efficiencies (without attenuation)
Definition: stir_x.h:665
void set_output_prefix(std::string prefix)
Set prefix for filenames with scatter estimates.
Definition: stir_x.h:693
PETScatterEstimator(std::string filename)
Overloaded constructor which takes the parameter file.
Definition: stir_x.h:650
Class for simulating the scatter contribution to PET data.
Definition: stir_x.h:538
PETSingleScatterSimulator(std::string filename)
Overloaded constructor which takes the parameter file.
Definition: stir_x.h:544
PETSingleScatterSimulator()
Default constructor.
Definition: stir_x.h:541
STIR ProjData wrapper with added functionality.
Definition: stir_data_containers.h:148
In-file implementation of STIRAcquisitionData.
Definition: stir_data_containers.h:483
STIR DiscretisedDensity<3, float> wrapper with added functionality.
Definition: stir_data_containers.h:855
Accessor classes.
Definition: stir_x.h:955
Definition: stir_x.h:1145
Definition: stir_x.h:983
Definition: stir_x.h:997
Definition: stir_x.h:1114
Definition: stir_x.h:1138
Definition: stir_x.h:1011
Definition: stir_x.h:990
Defines sirf::iequals.
Abstract data container.
Definition: GeometricalInfo.cpp:141
bool iequals(const std::string &a, const std::string &b)
Case insensitive string comparison, replaces boost::iequals.
Definition: iequals.cpp:7
DataProcessor3DF ImageDataProcessor
A typedef to use SIRF terminology for DataProcessors.
Definition: stir_x.h:297
Specification file for data handling types not present in STIR.