STIR 6.5.0
Scanner.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2000 PARAPET partners
3 Copyright (C) 2000-2010, Hammersmith Imanet Ltd
4 Copyright (C) 2011-2013, King's College London
5 Copyright (C) 2016, University of Hull
6 Copyright (C) 2016, 2019, 2021, 2023, 2024, 2026 UCL
7 Copyright 2017 ETH Zurich, Institute of Particle Physics and Astrophysics
8 Copyright (C 2017-2018, University of Leeds
9 Copyright (C) 2026, UMCG
10 This file is part of STIR.
11
12 SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
13
14 See STIR/LICENSE.txt for details
15*/
16
34#ifndef __stir_buildblock_SCANNER_H__
35#define __stir_buildblock_SCANNER_H__
36
40#include "stir/shared_ptr.h"
41#include "stir/deprecated.h"
42#include <string>
43#include <list>
44#include <vector>
45#include <cmath>
46#include <algorithm>
47#include <fstream>
48#include <boost/algorithm/string.hpp>
49#include <boost/unordered_map.hpp>
50
51START_NAMESPACE_STIR
52
53class Succeeded;
110{
111 friend class BlocksTests;
112 friend class ProjDataInfoCylindricalNoArcCorrTests;
113
114public:
115 /************* static members*****************************/
116 static Scanner* ask_parameters();
117
119 static Scanner* get_scanner_from_name(const std::string& name);
121 /* \return a string with one line per predefined scanner, listing the predefined names for
122 that scanner (separated by a comma)
123 */
124 static std::string list_all_names();
126 /* \return a list of strings, each element is a name of a predefined scanner.
127 If a scanner can have multiple names, only one name is returned, i.e.
128 the list has the same length as the number of predefined scanners.
129 */
130 static std::list<std::string> get_names_of_predefined_scanners();
131
132 // E931 HAS to be first, Unknown_scanner HAS to be last
133 // also, the list HAS to be consecutive (so DO NOT assign numbers here)
134 // finally, test_Scanner assumes E966 is the last in the list of CTI scanners
135 // supported by ecat_model from the LLN matrix library
136 // 08-3-2004, zlong, add user defined scanner
138 /* \a Userdefined_scanner can be used to set arbitrary scanner geometry info.
139 \a Unknown_scanner will be used when parsing (e.g. from an Interfile header)
140 to flag up an error and do some guess work in trying to recognise the scanner from
141 any given parameters.
142 */
143 enum Type
144 {
145 E931,
146 E951,
147 E953,
148 E921,
149 E925,
150 E961,
151 E962,
152 E966,
153 E1080,
154 test_scanner,
155 Siemens_mMR,
156 Siemens_mCT,
157 Siemens_Vision_600,
158 Siemens_Quadra,
159 RPT,
160 HiDAC,
161 Advance,
162 DiscoveryLS,
163 DiscoveryST,
164 DiscoverySTE,
165 DiscoveryRX,
166 Discovery600,
167 PETMR_Signa,
168 Discovery690,
169 DiscoveryMI3ring,
170 DiscoveryMI4ring,
171 DiscoveryMI5ring,
172 DiscoveryMI6ring,
173 HZLR,
174 RATPET,
175 PANDA,
176 HYPERimage,
177 nanoPET,
178 HRRT,
179 Allegro,
180 GeminiTF,
181 SAFIRDualRingPrototype,
182 UPENN_5rings,
183 UPENN_5rings_no_gaps,
184 UPENN_6rings,
185 UPENN_6rings_no_gaps,
186 User_defined_scanner,
187 Unknown_scanner
188 };
189
190 virtual ~Scanner() {}
191
193 Scanner(Type scanner_type);
194
196
201 Scanner(Type type_v,
202 const std::list<std::string>& list_of_names_v,
203 int num_detectors_per_ring_v,
204 int num_rings_v,
205 int max_num_non_arccorrected_bins_v,
206 int default_num_arccorrected_bins_v,
207 float inner_ring_radius_v,
208 float average_depth_of_interaction_v,
209 float ring_spacing_v,
210 float bin_size_v,
211 float intrinsic_tilt_v,
212 int num_axial_blocks_per_bucket_v,
213 int num_transaxial_blocks_per_bucket_v,
214 int num_axial_crystals_per_block_v,
215 int num_transaxial_crystals_per_block_v,
216 int num_axial_crystals_per_singles_unit_v,
217 int num_transaxial_crystals_per_singles_unit_v,
218 int num_detector_layers_v,
219 float energy_resolution_v = -1.0f,
220 float reference_energy_v = -1.0f,
221 short int max_num_of_timing_poss = -1,
222 float size_timing_pos = -1.0f,
223 float timing_resolution = -1.0f,
224 const std::string& scanner_geometry_v = "Cylindrical",
225 float axial_crystal_spacing_v = -1.0f,
226 float transaxial_crystal_spacing_v = -1.0f,
227 float axial_block_spacing_v = -1.0f,
228 float transaxial_block_spacing_v = -1.0f,
229 const std::string& crystal_map_file_name = "");
230
232
237 Scanner(Type type_v,
238 const std::string& name,
239 int num_detectors_per_ring_v,
240 int num_rings_v,
241 int max_num_non_arccorrected_bins_v,
242 int default_num_arccorrected_bins_v,
243 float inner_ring_radius_v,
244 float average_depth_of_interaction_v,
245 float ring_spacing_v,
246 float bin_size_v,
247 float intrinsic_tilt_v,
248 int num_axial_blocks_per_bucket_v,
249 int num_transaxial_blocks_per_bucket_v,
250 int num_axial_crystals_per_block_v,
251 int num_transaxial_crystals_per_block_v,
252 int num_axial_crystals_per_singles_unit_v,
253 int num_transaxial_crystals_per_singles_unit_v,
254 int num_detector_layers_v,
255 float energy_resolution_v = -1.0f,
256 float reference_energy_v = -1.0f,
257 short int max_num_of_timing_poss = -1,
258 float size_timing_pos = -1.0f,
259 float timing_resolution = -1.0f,
260 const std::string& scanner_geometry_v = "Cylindrical",
261 float axial_crystal_spacing_v = -1.0f,
262 float transaxial_crystal_spacing_v = -1.0f,
263 float axial_block_spacing_v = -1.0f,
264 float transaxial_block_spacing_v = -1.0f,
265 const std::string& crystal_map_file_name = "");
266
268
271 virtual void set_up();
272
274 std::string parameter_info() const;
276 const std::string& get_name() const;
278 const std::list<std::string>& get_all_names() const;
280 std::string list_names() const;
281
283 bool operator==(const Scanner& scanner) const;
284 inline bool operator!=(const Scanner& scanner) const;
285
287 inline Type get_type() const;
289
292 Succeeded check_consistency() const;
293
295
296
298 inline int get_num_rings() const;
300 inline int get_num_detectors_per_ring() const;
302
310 inline int get_max_num_non_arccorrected_bins() const;
312
317 inline int get_default_num_arccorrected_bins() const;
319
320 inline int get_max_num_views() const;
322 inline float get_inner_ring_radius() const;
324 inline float get_max_FOV_radius() const;
326 inline float get_effective_ring_radius() const;
328 inline float get_average_depth_of_interaction() const;
330 inline float get_ring_spacing() const;
332 inline float get_default_bin_size() const;
334
339 inline float get_intrinsic_azimuthal_tilt() const;
341
342
343 inline int get_num_transaxial_blocks_per_bucket() const;
345 inline int get_num_axial_blocks_per_bucket() const;
347 inline int get_num_axial_crystals_per_block() const;
349 inline int get_num_transaxial_crystals_per_block() const;
351 inline int get_num_transaxial_crystals_per_bucket() const;
353 inline int get_num_axial_crystals_per_bucket() const;
355 inline int get_num_detector_layers() const;
357 inline int get_num_axial_blocks() const;
359 inline int get_num_transaxial_blocks() const;
361 inline int get_num_axial_buckets() const;
363 inline int get_num_transaxial_buckets() const;
364
366 inline int get_num_axial_crystals_per_singles_unit() const;
368 inline int get_num_transaxial_crystals_per_singles_unit() const;
369 // TODO accomodate more complex geometries of singles units.
370 /* inline int get_num_crystal_layers_per_singles_unit() const; */
372 inline int get_num_axial_singles_units() const;
374 inline int get_num_transaxial_singles_units() const;
375 /* inline int get_num_layers_singles_units() const; */
376 inline int get_num_singles_units() const;
378
379 inline int get_max_num_timing_poss() const;
381
385 inline float get_size_of_timing_pos() const;
387
391 inline float get_timing_resolution() const;
393
400 float get_coincidence_window_width_in_ps() const;
402
403 float get_coincidence_window_width_in_mm() const;
404
406
413 int get_num_virtual_axial_crystals_per_block() const;
414 int get_num_virtual_transaxial_crystals_per_block() const;
415 void set_num_virtual_axial_crystals_per_block(int);
416 void set_num_virtual_transaxial_crystals_per_block(int);
418
420
421
423 inline std::string get_scanner_geometry() const;
425 inline float get_axial_crystal_spacing() const;
427 inline float get_transaxial_crystal_spacing() const;
429 inline float get_axial_block_spacing() const;
431 inline float get_transaxial_block_spacing() const;
436 inline float get_axial_length() const;
438
441 inline std::string get_crystal_map_file_name() const;
442
444
446
448
449
451
455 inline float get_energy_resolution() const;
457
458 inline float get_reference_energy() const;
460 inline bool has_energy_information() const;
461
463
465
470 // zlong, 08-04-2004, add set_methods
472 inline void set_type(const Type& new_type);
474 inline void set_num_rings(const int& new_num);
476 inline void set_num_detectors_per_ring(const int& new_num);
478 inline void set_max_num_non_arccorrected_bins(const int& new_num);
480 inline void set_default_num_arccorrected_bins(const int& new_num);
482 inline void set_inner_ring_radius(const float& new_radius);
484 inline void set_average_depth_of_interaction(const float& new_depth_of_interaction);
486 inline void set_ring_spacing(const float& new_spacing);
488 inline void set_default_bin_size(const float& new_size);
490 inline void set_intrinsic_azimuthal_tilt(const float new_tilt);
492
493
494 inline void set_num_transaxial_blocks_per_bucket(const int& new_num);
496 inline void set_num_axial_blocks_per_bucket(const int& new_num);
498 inline void set_num_axial_crystals_per_block(const int& new_num);
500 inline void set_num_transaxial_crystals_per_block(const int& new_num);
502 inline void set_num_detector_layers(const int& new_num);
504 inline void set_num_axial_crystals_per_singles_unit(const int& new_num);
506 inline void set_num_transaxial_crystals_per_singles_unit(const int& new_num);
507 // TODO accomodate more complex geometries of singles units.
509
511
519 void set_scanner_geometry(const std::string& new_scanner_geometry);
521 inline void set_axial_crystal_spacing(const float& new_spacing);
523 inline void set_transaxial_crystal_spacing(const float& new_spacing);
525 inline void set_axial_block_spacing(const float& new_spacing);
527 inline void set_transaxial_block_spacing(const float& new_spacing);
529
530 inline void set_crystal_map_file_name(const std::string& new_crystal_map_file_name);
532
534
536 inline void set_energy_resolution(const float new_num);
538
539 inline void set_reference_energy(const float new_num);
541 inline void set_max_num_timing_poss(int new_num);
543 inline void set_size_of_timing_poss(float new_num);
545 inline void set_timing_resolution(float new_num_in_ps);
547
549
551 inline int get_singles_bin_index(int axial_index, int transaxial_index) const;
552
555 inline int get_singles_bin_index(const DetectionPosition<>& det_pos) const;
556
558 inline int get_axial_singles_unit(int singles_bin_index) const;
559
561 inline int get_transaxial_singles_unit(int singles_bin_index) const;
562
564 inline bool is_tof_ready() const;
565
566 inline bool is_already_setup() const { return _already_setup; }
567
569 // used in CListRecordSAFIR.inl for accessing the coordinates
570 inline stir::DetectionPosition<> get_det_pos_for_index(const stir::DetectionPosition<>& det_pos) const;
572 // used in ProjInfoDataGenericNoArcCorr.cxx for accessing the coordinates
573 inline stir::CartesianCoordinate3D<float> get_coordinate_for_det_pos(const stir::DetectionPosition<>& det_pos) const;
575 inline stir::CartesianCoordinate3D<float> get_coordinate_for_index(const stir::DetectionPosition<>& det_pos) const;
577 // used in ProjInfoDataGenericNoArcCorr.cxx for accessing the get_bin
578 inline Succeeded find_detection_position_given_cartesian_coordinate(DetectionPosition<>& det_pos,
579 const CartesianCoordinate3D<float>& cart_coord) const;
580
581 shared_ptr<const DetectorCoordinateMap> STIR_DEPRECATED get_detector_map_sptr() const { return detector_map_sptr; }
582 shared_ptr<const DetectorCoordinateMap> get_detector_coordinate_map_sptr() const { return detector_map_sptr; }
583 const DetectorCoordinateMap& get_detector_coordinate_map() const { return *detector_map_sptr; }
584
585private:
586 bool _already_setup;
587 Type type;
588 std::list<std::string> list_of_names;
589 int num_rings; /* number of direct planes */
590 int max_num_non_arccorrected_bins;
591 int default_num_arccorrected_bins; /* default number of bins */
592 int num_detectors_per_ring;
593
594 float inner_ring_radius;
595 float average_depth_of_interaction;
596 float max_FOV_radius;
597 float ring_spacing;
598 float bin_size;
599 float intrinsic_tilt;
600
601 int num_transaxial_blocks_per_bucket; /* transaxial blocks per bucket */
602 int num_axial_blocks_per_bucket; /* axial blocks per bucket */
603 int num_axial_crystals_per_block; /* number of crystals in the axial direction */
604 int num_transaxial_crystals_per_block; /* number of transaxial crystals */
605 int num_detector_layers;
606
607 int num_axial_crystals_per_singles_unit;
608 int num_transaxial_crystals_per_singles_unit;
609
615 float energy_resolution;
618 float reference_energy;
620 float timing_resolution;
622 int max_num_of_timing_poss;
624 float size_timing_pos;
625
628
629 std::string scanner_geometry;
630 float axial_crystal_spacing;
631 float transaxial_crystal_spacing;
632 float axial_block_spacing;
633 float transaxial_block_spacing;
635 std::string crystal_map_file_name;
636 shared_ptr<const DetectorCoordinateMap> detector_map_sptr;
637
639 void set_detector_coordinate_map_sptr(shared_ptr<const DetectorCoordinateMap> new_map_sptr);
641 void set_detector_coordinate_map(const DetectorCoordinateMap& coord_map);
642 void initialise_max_FOV_radius();
643
644 // function to create the maps
645 void read_detectormap_from_file(const std::string& filename);
646
647 // ! set all parameters
648 void set_params(Type type_v,
649 const std::list<std::string>& list_of_names_v,
650 int num_rings_v,
651 int max_num_non_arccorrected_bins_v,
652 int default_num_arccorrected_bins_v,
653 int num_detectors_per_ring_v,
654 float inner_ring_radius_v,
655 float average_depth_of_interaction_v,
656 float ring_spacing_v,
657 float bin_size_v,
658 float intrinsic_tilt_v,
659 int num_axial_blocks_per_bucket_v,
660 int num_transaxial_blocks_per_bucket_v,
661 int num_axial_crystals_per_block_v,
662 int num_transaxial_crystals_per_block_v,
663 int num_axial_crystals_per_singles_unit_v,
664 int num_transaxial_crystals_per_singles_unit_v,
665 int num_detector_layers_v,
666 float energy_resolution_v = -1.0f,
667 float reference_energy = -1.0f,
668 short int max_num_of_timing_poss_v = -1.0f,
669 float size_timing_pos_v = -1.0f,
670 float timing_resolution_v = -1.0f,
671 const std::string& scanner_geometry_v = "",
672 float axial_crystal_spacing_v = -1.0f,
673 float transaxial_crystal_spacing_v = -1.0f,
674 float axial_block_spacing_v = -1.0f,
675 float transaxial_block_spacing_v = -1.0f,
676 const std::string& crystal_map_file_name = "");
677};
678
679END_NAMESPACE_STIR
680
681#include "stir/Scanner.inl"
682
683#endif
defines the stir::CartesianCoordinate3D<coordT> class
Declaration of class stir::DetectionPosition.
Declaration of class stir::DetectorCoordinateMap.
implementation of inline functions of class Scanner
A class for storing some info on the scanner.
Definition Scanner.h:110
static std::string list_all_names()
get a string listing names for all predefined scanners
Definition Scanner.cxx:2280
static std::list< std::string > get_names_of_predefined_scanners()
get a list with the names for each predefined scanner
Definition Scanner.cxx:2299
Type
enum for all predefined scanners
Definition Scanner.h:144
Scanner(Type scanner_type)
constructor that takes scanner type as an input argument
Definition Scanner.cxx:65
static Scanner * get_scanner_from_name(const std::string &name)
get the scanner pointer from the name
Definition Scanner.cxx:2247
This file declares a deprecation macro.
#define STIR_DEPRECATED
Deprecation macro.
Definition deprecated.h:21
Import of std::shared_ptr, std::dynamic_pointer_cast and std::static_pointer_cast into the stir names...