STIR  6.2.0
DetectorCoordinateMap.h
Go to the documentation of this file.
1 /*
2  Copyright 2015, 2017 ETH Zurich, Institute of Particle Physics
3  Copyright 2020 Positrigo AG, Zurich
4  Copyright (C) 2021 University College London
5  This file is part of STIR.
6 
7  SPDX-License-Identifier: Apache-2.0
8 
9  See STIR/LICENSE.txt for details
10  */
11 
23 #include <fstream>
24 #include <string>
25 #include <vector>
26 #include <random>
27 #include <map>
28 #include <boost/algorithm/string.hpp>
29 #include <boost/unordered_map.hpp>
30 #ifdef STIR_OPENMP
31 # include <omp.h>
32 #endif
33 
35 #include "stir/DetectionPosition.h"
36 
37 #ifndef __stir_DetectorCoordinateMap_H__
38 # define __stir_DetectorCoordinateMap_H__
39 
40 START_NAMESPACE_STIR
41 
42 class Succeeded;
43 
51 {
52  struct ihash
53  {
54  std::size_t operator()(stir::DetectionPosition<> const& detpos) const
55  {
56  std::size_t seed = 0;
57  boost::hash_combine(seed, detpos.axial_coord());
58  boost::hash_combine(seed, detpos.radial_coord());
59  boost::hash_combine(seed, detpos.tangential_coord());
60  return seed;
61  }
62  };
63 
64 public:
65  typedef boost::unordered_map<stir::DetectionPosition<>, stir::CartesianCoordinate3D<float>, ihash> det_pos_to_coord_type;
66  typedef boost::unordered_map<stir::DetectionPosition<>, stir::DetectionPosition<>, ihash> unordered_to_ordered_det_pos_type;
67 
69  DetectorCoordinateMap(const std::string& filename, double sigma = 0.0)
70  : DetectorCoordinateMap(sigma)
71  {
72  read_detectormap_from_file(filename);
73  }
75  DetectorCoordinateMap(const det_pos_to_coord_type& coord_map, double sigma = 0.0)
76  : DetectorCoordinateMap(sigma)
77  {
78  set_detector_map(coord_map);
79  }
80 
82  void read_detectormap_from_file(const std::string& filename);
84 
85  void set_detector_map(const det_pos_to_coord_type& coord_map);
86 
87  stir::DetectionPosition<> get_det_pos_for_index(const stir::DetectionPosition<>& index) const
88  {
89  return input_index_to_det_pos.at(index);
90  }
92  stir::CartesianCoordinate3D<float> get_coordinate_for_det_pos(const stir::DetectionPosition<>& det_pos) const
93  {
94  auto coord = det_pos_to_coord.at(det_pos);
95  if (sigma == 0.0)
96  return coord;
97 
98 # ifdef STIR_OPENMP
99  auto thread_id = omp_get_thread_num();
100 # else
101  auto thread_id = 0;
102 # endif
103 
104  coord.x() += static_cast<float>(distributions[thread_id](generators[thread_id]));
105  coord.y() += static_cast<float>(distributions[thread_id](generators[thread_id]));
106  coord.z() += static_cast<float>(distributions[thread_id](generators[thread_id]));
107  return coord;
108  }
110  stir::CartesianCoordinate3D<float> get_coordinate_for_index(const stir::DetectionPosition<>& index) const
111  {
112  return get_coordinate_for_det_pos(get_det_pos_for_index(index));
113  }
114 
115  Succeeded find_detection_position_given_cartesian_coordinate(DetectionPosition<>& det_pos,
116  const CartesianCoordinate3D<float>& cart_coord) const;
117 
118  unsigned get_num_tangential_coords() const { return num_tangential_coords; }
119  unsigned get_num_axial_coords() const { return num_axial_coords; }
120  unsigned get_num_radial_coords() const { return num_radial_coords; }
121 
122 protected:
123  explicit DetectorCoordinateMap(double sigma = 0.0)
124  : sigma(sigma)
125  {
126 # ifdef STIR_OPENMP
127  generators.resize(omp_get_max_threads());
128  distributions.resize(omp_get_max_threads());
129  for (auto& distribution : distributions)
130  distribution = std::normal_distribution<double>(0.0, sigma);
131 # else
132  generators.resize(1);
133  distributions.resize(1);
134  distributions[0] = std::normal_distribution<double>(0.0, sigma);
135 # endif
136  }
137 
138 private:
139  unsigned num_tangential_coords;
140  unsigned num_axial_coords;
141  unsigned num_radial_coords;
142  unordered_to_ordered_det_pos_type input_index_to_det_pos;
143  det_pos_to_coord_type det_pos_to_coord;
144  std::map<stir::CartesianCoordinate3D<float>, stir::DetectionPosition<>>
145  detection_position_map_given_cartesian_coord_keys_3_decimal;
146  std::map<stir::CartesianCoordinate3D<float>, stir::DetectionPosition<>>
147  detection_position_map_given_cartesian_coord_keys_2_decimal;
148 
149  const double sigma;
150  mutable std::vector<std::default_random_engine> generators;
151  mutable std::vector<std::normal_distribution<double>> distributions;
152 
153  static det_pos_to_coord_type read_detectormap_from_file_help(const std::string& crystal_map_name);
154 };
155 
156 END_NAMESPACE_STIR
157 #endif
stir::CartesianCoordinate3D< float > get_coordinate_for_index(const stir::DetectionPosition<> &index) const
Returns a cartesian coordinate given an (unsorted) index.
Definition: DetectorCoordinateMap.h:110
stir::CartesianCoordinate3D< float > get_coordinate_for_det_pos(const stir::DetectionPosition<> &det_pos) const
Returns a cartesian coordinate given a detection position.
Definition: DetectorCoordinateMap.h:92
DetectorCoordinateMap(const det_pos_to_coord_type &coord_map, double sigma=0.0)
Constructor calls set_detector_map(coord_map).
Definition: DetectorCoordinateMap.h:75
DetectorCoordinateMap(const std::string &filename, double sigma=0.0)
Constructor calls read_detectormap_from_file( filename ).
Definition: DetectorCoordinateMap.h:69
Declaration of class stir::DetectionPosition.
Definition: DetectorCoordinateMap.h:50
coordT & at(const int d)
Return value at index t (which is 1-based), but with range checking (throws std::out_of_range) ...
Definition: BasicCoordinate.inl:90
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition: Succeeded.h:43
defines the stir::CartesianCoordinate3D<coordT> class