STIR 6.4.0
Scanner.inl
Go to the documentation of this file.
1//
2//
3/*
4 Copyright (C) 2000 PARAPET partners
5 Copyright (C) 2000- 2007, Hammersmith Imanet Ltd
6 Copyright (C) 2016, 2021 University College London
7 Copyright 2017 ETH Zurich, Institute of Particle Physics and Astrophysics
8 This file is part of STIR.
9
10 SPDX-License-Identifier: Apache-2.0 AND License-ref-PARAPET-license
11
12 See STIR/LICENSE.txt for details
13*/
28#include "stir/error.h"
29#include "stir/Succeeded.h"
30
31START_NAMESPACE_STIR
32
33bool
34Scanner::operator!=(const Scanner& scanner) const
35{
36 return !(*this == scanner);
37}
38
39Scanner::Type
41{
42 return type;
43}
44
45int
47{
48 return num_rings;
49}
50int
52{
53 return num_detectors_per_ring;
54}
55int
57{
58 return max_num_non_arccorrected_bins;
59}
60
61int
66
67int
69{
70 return default_num_arccorrected_bins;
71}
72
73float
75{
76 return inner_ring_radius;
77}
78
79float
81{
82 return max_FOV_radius;
83}
84
85float
87{
88 return average_depth_of_interaction;
89}
90
91float
93{
94 return inner_ring_radius + average_depth_of_interaction;
95}
96
97float
99{
100 return ring_spacing;
101}
102
103float
105{
106 return bin_size;
107}
108
109float
111{
112#ifdef STIR_LEGACY_IGNORE_VIEW_OFFSET
113 return 0.F;
114#else
115 return intrinsic_tilt;
116#endif
117}
118
119int
121{
122 return num_transaxial_blocks_per_bucket;
123}
124
125int
127{
128 return num_axial_blocks_per_bucket;
129}
130
131int
133{
134 return num_axial_crystals_per_block;
135}
136
137int
139{
140 return num_transaxial_crystals_per_block;
141}
142
143int
148
149int
154
155int
157{
158 return num_detector_layers;
159}
160
161int
163{
164 // when using virtual crystals between blocks, there won't be one at the end, so we
165 // need to take this into account.
166 return (num_rings + get_num_virtual_axial_crystals_per_block()) / num_axial_crystals_per_block;
167}
168
169int
171{
172 return num_detectors_per_ring / num_transaxial_crystals_per_block;
173}
174
175int
177{
178 return get_num_axial_blocks() / num_axial_blocks_per_bucket;
179}
180
181int
183{
184 return get_num_transaxial_blocks() / num_transaxial_blocks_per_bucket;
185}
186
187int
189{
190 return num_axial_crystals_per_singles_unit;
191}
192
193int
195{
196 return num_transaxial_crystals_per_singles_unit;
197}
198
199int
201{
202 if (num_axial_crystals_per_singles_unit == 0)
203 {
204 return 0;
205 }
206 else
207 {
208 return (num_rings + get_num_virtual_axial_crystals_per_block()) / num_axial_crystals_per_singles_unit;
209 }
210}
211
212int
214{
215 if (num_transaxial_crystals_per_singles_unit == 0)
216 {
217 return 0;
218 }
219 else
220 {
221 return num_detectors_per_ring / num_transaxial_crystals_per_singles_unit;
222 }
223}
224
225int
226Scanner::get_num_singles_units() const
227{
228 // TODO Accomodate more complex (multi-layer) geometries.
229 return get_num_axial_singles_units() * get_num_transaxial_singles_units();
230}
231
232float
234{
235 return energy_resolution;
236}
237
238float
240{
241 return reference_energy;
242}
243
244int
246{
247 return max_num_of_timing_poss;
248}
249
250float
252{
253 return size_timing_pos;
254}
255
256float
258{
259 return timing_resolution;
260}
261
262bool
264{
265 return (max_num_of_timing_poss > 0 && size_timing_pos > 0.0f && timing_resolution > 0.0f);
266}
267
268std::string
270{
271 return scanner_geometry;
272}
273
274float
276{
277 return axial_crystal_spacing;
278}
279
280float
282{
283 return transaxial_crystal_spacing;
284}
285
286float
288{
289 return transaxial_block_spacing;
290}
291
292float
294{
295 return axial_block_spacing;
296}
297
298float
300{
301 if (get_scanner_geometry() == "Cylindrical")
302 {
303 return get_num_rings() * get_ring_spacing();
304 }
305 else if (get_scanner_geometry() == "Generic")
306 {
307 error("get_axial_length not yet implemented for Generic scanner geometry");
308 }
311}
312
313std::string
314Scanner::get_crystal_map_file_name() const
315{
316 return crystal_map_file_name;
317}
318
319//************************ set ******************************8
320
321void
322Scanner::set_type(const Type& new_type)
323{
324 type = new_type;
325 _already_setup = false;
326}
327
328void
329Scanner::set_num_rings(const int& new_num)
330{
331 num_rings = new_num;
332 _already_setup = false;
333}
334
335void
337{
338 num_detectors_per_ring = new_num;
339 _already_setup = false;
340}
341
342void
344{
345 max_num_non_arccorrected_bins = new_num;
346 _already_setup = false;
347}
348
349void
351{
352 default_num_arccorrected_bins = new_num;
353 _already_setup = false;
354}
355
356void
357Scanner::set_inner_ring_radius(const float& new_radius)
358{
359 inner_ring_radius = new_radius;
360 _already_setup = false;
361}
362
363void
364Scanner::set_average_depth_of_interaction(const float& new_depth_of_interaction)
365{
366 average_depth_of_interaction = new_depth_of_interaction;
367 _already_setup = false;
368}
369
370bool
372{
373 return (energy_resolution <= 0.0 || reference_energy <= 0.0) ? false : true;
374}
375
376void
377Scanner::set_ring_spacing(const float& new_spacing)
378{
379 ring_spacing = new_spacing;
380}
381
382void
383Scanner::set_default_bin_size(const float& new_size)
384{
385 bin_size = new_size;
386 _already_setup = false;
387}
388
389void
391{
392 intrinsic_tilt = new_tilt;
393 _already_setup = false;
394}
395
396void
398{
399 num_transaxial_blocks_per_bucket = new_num;
400 _already_setup = false;
401}
402
403void
405{
406 num_axial_blocks_per_bucket = new_num;
407 _already_setup = false;
408}
409
410void
412{
413 num_detector_layers = new_num;
414 _already_setup = false;
415}
416
417void
419{
420 num_axial_crystals_per_block = new_num;
421 _already_setup = false;
422}
423
424void
426{
427 num_transaxial_crystals_per_block = new_num;
428 _already_setup = false;
429}
430
431void
433{
434 num_axial_crystals_per_singles_unit = new_num;
435 _already_setup = false;
436}
437
438void
440{
441 num_transaxial_crystals_per_singles_unit = new_num;
442 _already_setup = false;
443}
444
445void
447{
448 energy_resolution = new_num;
449 _already_setup = false;
450}
451
452void
454{
455 reference_energy = new_num;
456 _already_setup = false;
457}
458
459void
460Scanner::set_axial_crystal_spacing(const float& new_spacing)
461{
462 axial_crystal_spacing = new_spacing;
463 _already_setup = false;
464}
465
466void
468{
469 transaxial_crystal_spacing = new_spacing;
470 _already_setup = false;
471}
472
473void
475{
476 transaxial_block_spacing = new_spacing;
477 _already_setup = false;
478}
479
480void
481Scanner::set_axial_block_spacing(const float& new_spacing)
482{
483 axial_block_spacing = new_spacing;
484 _already_setup = false;
485}
486
487void
488Scanner::set_crystal_map_file_name(const std::string& new_crystal_map_file_name)
489{
490 crystal_map_file_name = new_crystal_map_file_name;
491 _already_setup = false;
492}
493
494void
496{
497 max_num_of_timing_poss = new_num;
498 _already_setup = false;
499}
500
501void
503{
504 size_timing_pos = new_num;
505 _already_setup = false;
506}
507
508void
509Scanner::set_timing_resolution(const float new_num_in_ps)
510{
511 timing_resolution = new_num_in_ps;
512 _already_setup = false;
513}
514
515/******** Calculate singles bin index from detection position *********/
516
517int
518Scanner::get_singles_bin_index(int axial_index, int transaxial_index) const
519{
520 // TODO: Accomodate more complex geometry.
521 return (transaxial_index + (axial_index * get_num_transaxial_singles_units()));
522}
523
524int
526{
527
528 // TODO: Accomodate more complex geometry.
529
530 int axial_index = det_pos.axial_coord() / get_num_axial_crystals_per_singles_unit();
531
532 int transaxial_index = det_pos.tangential_coord() / get_num_transaxial_crystals_per_singles_unit();
533
534 // return(transaxial_index + (axial_index * get_num_transaxial_singles_units()));
535 return (get_singles_bin_index(axial_index, transaxial_index));
536}
537
538// Get the axial singles bin coordinate from a singles bin.
539int
540Scanner::get_axial_singles_unit(int singles_bin_index) const
541{
542 // TODO: Accomodate more complex geometry.
543 return (singles_bin_index / get_num_transaxial_singles_units());
544}
545
546// Get the transaxial singles bin coordinate from a singles bin.
547int
548Scanner::get_transaxial_singles_unit(int singles_bin_index) const
549{
550 // TODO: Accomodate more complex geometry.
551 return (singles_bin_index % get_num_transaxial_singles_units());
552}
553
554// For retrieving the coordinates / detector, ring id from the scanner
557{
558 if (!detector_map_sptr)
559 stir::error("Scanner: detector_map not defined. Did you run set_up()?");
560
561 return detector_map_sptr->get_det_pos_for_index(det_pos);
562}
563
566{
567 if (!_already_setup)
568 stir::error("Scanner: you forgot to call set_up().");
569 if (!detector_map_sptr)
570 stir::error("Scanner: detector_map not defined. Did you run set_up()?");
571
572 return detector_map_sptr->get_coordinate_for_det_pos(det_pos);
573}
574
577{
578 if (!_already_setup)
579 stir::error("Scanner: you forgot to call set_up().");
580 if (!detector_map_sptr)
581 stir::error("Scanner: detector_map not defined. Did you run set_up()?");
582
583 return detector_map_sptr->get_coordinate_for_index(index);
584}
585
588 const CartesianCoordinate3D<float>& cart_coord) const
589{
590 if (!_already_setup)
591 stir::error("Scanner: you forgot to call set_up().");
592 if (!detector_map_sptr)
593 stir::error("Scanner: detector_map not defined. Did you run set_up()?");
594
595 return detector_map_sptr->find_detection_position_given_cartesian_coordinate(det_pos, cart_coord);
596}
597
598END_NAMESPACE_STIR
Declaration of class stir::Succeeded.
a templated class for 3-dimensional coordinates.
Definition CartesianCoordinate3D.h:53
A class for storing coordinates of a detection.
Definition DetectionPosition.h:61
int get_max_num_timing_poss() const
Get the maximum number of TOF bins.
Definition Scanner.inl:245
float get_reference_energy() const
get the reference energy in keV of the energy resolution
Definition Scanner.inl:239
float get_default_bin_size() const
get default arc-corrected bin size
Definition Scanner.inl:104
Type get_type() const
get scanner type
Definition Scanner.inl:40
int get_num_axial_blocks() const
get number of axial blocks
Definition Scanner.inl:162
float get_axial_length() const
Definition Scanner.inl:299
void set_num_axial_crystals_per_singles_unit(const int &new_num)
set number of axial crystals per singles unit
Definition Scanner.inl:432
void set_average_depth_of_interaction(const float &new_depth_of_interaction)
set average depth of interaction
Definition Scanner.inl:364
int get_singles_bin_index(int axial_index, int transaxial_index) const
Calculate a singles bin index from axial and transaxial singles bin coordinates.
Definition Scanner.inl:518
bool has_energy_information() const
true if energy_resolution and reference_energy are set
Definition Scanner.inl:371
void set_reference_energy(const float new_num)
set the reference energy (in keV) of the energy resolution
Definition Scanner.inl:453
void set_size_of_timing_poss(float new_num)
Set the delta t which correspnds to the max number of TOF bins.
Definition Scanner.inl:502
void set_num_detector_layers(const int &new_num)
set number of crystal layers (for DOI)
Definition Scanner.inl:411
void set_default_num_arccorrected_bins(const int &new_num)
set the default number of arccorrected_bins
Definition Scanner.inl:350
stir::CartesianCoordinate3D< float > get_coordinate_for_det_pos(const stir::DetectionPosition<> &det_pos) const
Get the Cartesian coordinates (x,y,z) given the STIR detection position (det#, ring#,...
Definition Scanner.inl:565
void set_crystal_map_file_name(const std::string &new_crystal_map_file_name)
set crystal map file name for the generic geometry
Definition Scanner.inl:488
Succeeded find_detection_position_given_cartesian_coordinate(DetectionPosition<> &det_pos, const CartesianCoordinate3D< float > &cart_coord) const
Find detection position at a coordinate.
Definition Scanner.inl:587
float get_intrinsic_azimuthal_tilt() const
get intrinsic tilt in raw sinogram data (in radians)
Definition Scanner.inl:110
int get_num_axial_buckets() const
get number of axial buckets
Definition Scanner.inl:176
int get_num_transaxial_singles_units() const
get number of transaxial singles unit
Definition Scanner.inl:213
void set_type(const Type &new_type)
set scanner type
Definition Scanner.inl:322
int get_num_transaxial_buckets() const
get number of axial buckets
Definition Scanner.inl:182
void set_transaxial_crystal_spacing(const float &new_spacing)
set crystal spacing in transaxial direction
Definition Scanner.inl:467
void set_num_rings(const int &new_num)
set number of rings
Definition Scanner.inl:329
int get_num_transaxial_crystals_per_bucket() const
get crystals in a bucket
Definition Scanner.inl:150
int get_num_detector_layers() const
get number of crystal layers (for DOI)
Definition Scanner.inl:156
int get_num_axial_crystals_per_bucket() const
get crystals in a bucket
Definition Scanner.inl:144
float get_size_of_timing_pos() const
Get the size for one (unmashed) TOF bin in picoseconds.
Definition Scanner.inl:251
int get_num_transaxial_crystals_per_singles_unit() const
get number of transaxial crystals per singles unit.
Definition Scanner.inl:194
int get_num_detectors_per_ring() const
get the number of detectors per ring
Definition Scanner.inl:51
void set_num_transaxial_crystals_per_singles_unit(const int &new_num)
set number of transaxial crystals per singles unit
Definition Scanner.inl:439
float get_energy_resolution() const
get the energy resolution as a fraction at the reference energy
Definition Scanner.inl:233
Type
enum for all predefined scanners
Definition Scanner.h:141
int get_num_axial_crystals_per_singles_unit() const
get number of axial crystals per singles unit
Definition Scanner.inl:188
int get_axial_singles_unit(int singles_bin_index) const
Get the axial singles bin coordinate from a singles bin.
Definition Scanner.inl:540
std::string get_scanner_geometry() const
get scanner geometry
Definition Scanner.inl:269
int get_num_axial_singles_units() const
get number of axial singles units
Definition Scanner.inl:200
void set_num_transaxial_blocks_per_bucket(const int &new_num)
set number of transaxial blocks per bucket
Definition Scanner.inl:397
void set_ring_spacing(const float &new_spacing)
set ring spacing
Definition Scanner.inl:377
int get_transaxial_singles_unit(int singles_bin_index) const
Get the transaxial singles bin coordinate from a singles bin.
Definition Scanner.inl:548
float get_inner_ring_radius() const
get inner ring radius
Definition Scanner.inl:74
void set_num_axial_blocks_per_bucket(const int &new_num)
set number of axial blocks per bucket
Definition Scanner.inl:404
void set_timing_resolution(float new_num_in_ps)
Set timing resolution.
Definition Scanner.inl:509
int get_num_transaxial_blocks() const
get number of axial blocks
Definition Scanner.inl:170
float get_ring_spacing() const
get ring spacing
Definition Scanner.inl:98
void set_default_bin_size(const float &new_size)
set default arc-corrected bin size
Definition Scanner.inl:383
void set_num_axial_crystals_per_block(const int &new_num)
set number of crystals in the axial direction
Definition Scanner.inl:418
float get_average_depth_of_interaction() const
get average depth of interaction
Definition Scanner.inl:86
void set_max_num_non_arccorrected_bins(const int &new_num)
set the maximum number of arccorrected bins
Definition Scanner.inl:343
void set_transaxial_block_spacing(const float &new_spacing)
set block spacing in transaxial direction
Definition Scanner.inl:474
int get_default_num_arccorrected_bins() const
get the default number of arccorrected tangential positions
Definition Scanner.inl:68
void set_num_detectors_per_ring(const int &new_num)
set the namber of detectors per ring
Definition Scanner.inl:336
float get_axial_block_spacing() const
get block spacing in axial direction
Definition Scanner.inl:293
int get_num_axial_blocks_per_bucket() const
get number of axial blocks per bucket
Definition Scanner.inl:126
int get_num_virtual_axial_crystals_per_block() const
Definition Scanner.cxx:1638
int get_num_rings() const
get number of rings
Definition Scanner.inl:46
stir::DetectionPosition get_det_pos_for_index(const stir::DetectionPosition<> &det_pos) const
Get the STIR detection position (det#, ring#, layer#) given the detection position id in the input cr...
Definition Scanner.inl:556
int get_num_transaxial_crystals_per_block() const
get number of transaxial crystals
Definition Scanner.inl:138
void set_max_num_timing_poss(int new_num)
Set the maximum number of TOF bins.
Definition Scanner.inl:495
bool is_tof_ready() const
True if it is TOF compatible.
Definition Scanner.inl:263
int get_max_num_views() const
get maximum number of views
Definition Scanner.inl:62
int get_num_transaxial_blocks_per_bucket() const
get number of transaxial blocks per bucket
Definition Scanner.inl:120
void set_axial_block_spacing(const float &new_spacing)
set block spacing in axial direction
Definition Scanner.inl:481
float get_transaxial_crystal_spacing() const
get crystal spacing in transaxial direction
Definition Scanner.inl:281
void set_inner_ring_radius(const float &new_radius)
set inner ring radius
Definition Scanner.inl:357
void set_axial_crystal_spacing(const float &new_spacing)
set crystal spacing in axial direction
Definition Scanner.inl:460
void set_energy_resolution(const float new_num)
set the energy resolution of the system
Definition Scanner.inl:446
int get_num_axial_crystals_per_block() const
get number of crystals in the axial direction
Definition Scanner.inl:132
float get_transaxial_block_spacing() const
get block spacing in transaxial direction
Definition Scanner.inl:287
void set_intrinsic_azimuthal_tilt(const float new_tilt)
in degrees
Definition Scanner.inl:390
float get_effective_ring_radius() const
get effective ring radius
Definition Scanner.inl:92
float get_timing_resolution() const
Get the timing resolution of the scanner in picoseconds.
Definition Scanner.inl:257
float get_axial_crystal_spacing() const
get crystal spacing in axial direction
Definition Scanner.inl:275
int get_max_num_non_arccorrected_bins() const
get the maximum number of arccorrected tangential positions
Definition Scanner.inl:56
void set_num_transaxial_crystals_per_block(const int &new_num)
set number of transaxial crystals
Definition Scanner.inl:425
float get_max_FOV_radius() const
get maximum field of view radius
Definition Scanner.inl:80
stir::CartesianCoordinate3D< float > get_coordinate_for_index(const stir::DetectionPosition<> &det_pos) const
Get the Cartesian coordinates (x,y,z) given the detection position id in the input crystal map.
Definition Scanner.inl:576
a class containing an enumeration type that can be used by functions to signal successful operation o...
Definition Succeeded.h:44
Declaration of stir::error()
void error(const char *const s,...)
Print error with format string a la printf and throw exception.
Definition error.cxx:42