diff --git a/src/IO/InterfileHeader.cxx b/src/IO/InterfileHeader.cxx index b1539e150c..ea81f98a31 100644 --- a/src/IO/InterfileHeader.cxx +++ b/src/IO/InterfileHeader.cxx @@ -600,6 +600,12 @@ InterfilePDFSHeader::InterfilePDFSHeader() num_transaxial_crystals_per_block = 0; add_key("number of crystals_per_block in transaxial direction", &num_transaxial_crystals_per_block); + num_virtual_axial_crystals_per_block = 0; + add_key("number of virtual crystals_per_block in axial direction", + &num_virtual_axial_crystals_per_block); + num_virtual_transaxial_crystals_per_block = 0; + add_key("number of virtual crystals_per_block in transaxial direction", + &num_virtual_transaxial_crystals_per_block); num_axial_crystals_per_singles_unit = -1; add_key("number of crystals_per_singles_unit in axial direction", &num_axial_crystals_per_singles_unit); @@ -1095,6 +1101,10 @@ bool InterfilePDFSHeader::post_processing() num_axial_crystals_per_block = guessed_scanner_ptr->get_num_axial_crystals_per_block(); if (num_transaxial_crystals_per_block<=0) num_transaxial_crystals_per_block = guessed_scanner_ptr->get_num_transaxial_crystals_per_block(); + if (num_virtual_axial_crystals_per_block<=0) + num_virtual_axial_crystals_per_block = guessed_scanner_ptr->get_num_virtual_axial_crystals_per_block(); + if (num_virtual_transaxial_crystals_per_block<=0) + num_virtual_transaxial_crystals_per_block = guessed_scanner_ptr->get_num_virtual_transaxial_crystals_per_block(); if (num_axial_crystals_per_singles_unit < 0) num_axial_crystals_per_singles_unit = guessed_scanner_ptr->get_num_axial_crystals_per_singles_unit(); @@ -1192,6 +1202,22 @@ bool InterfilePDFSHeader::post_processing() num_transaxial_crystals_per_block, guessed_scanner_ptr->get_num_transaxial_crystals_per_block()); mismatch_between_header_and_guess = true; } + if ( + guessed_scanner_ptr->get_num_virtual_axial_crystals_per_block()>=0 && + num_virtual_axial_crystals_per_block!= guessed_scanner_ptr->get_num_virtual_axial_crystals_per_block()) + { + warning("Interfile warning: num_virtual_axial_crystals_per_block (%d) is expected to be %d.\n", + num_virtual_axial_crystals_per_block, guessed_scanner_ptr->get_num_virtual_axial_crystals_per_block()); + mismatch_between_header_and_guess = true; + } + if ( + guessed_scanner_ptr->get_num_virtual_transaxial_crystals_per_block()>0 && + num_virtual_transaxial_crystals_per_block!= guessed_scanner_ptr->get_num_virtual_transaxial_crystals_per_block()) + { + warning("Interfile warning: num_transaxial_crystals_per_block (%d) is expected to be %d.\n", + num_transaxial_crystals_per_block, guessed_scanner_ptr->get_num_transaxial_crystals_per_block()); + mismatch_between_header_and_guess = true; + } if ( guessed_scanner_ptr->get_num_axial_crystals_per_singles_unit() > 0 && num_axial_crystals_per_singles_unit != guessed_scanner_ptr->get_num_axial_crystals_per_singles_unit() ) @@ -1302,6 +1328,8 @@ bool InterfilePDFSHeader::post_processing() num_transaxial_blocks_per_bucket, num_axial_crystals_per_block, num_transaxial_crystals_per_block, + num_virtual_axial_crystals_per_block, + num_virtual_transaxial_crystals_per_block, num_axial_crystals_per_singles_unit, num_transaxial_crystals_per_singles_unit, num_detector_layers, diff --git a/src/IO/InterfilePDFSHeaderSPECT.cxx b/src/IO/InterfilePDFSHeaderSPECT.cxx index 6012292fee..ba2513079f 100644 --- a/src/IO/InterfilePDFSHeaderSPECT.cxx +++ b/src/IO/InterfilePDFSHeaderSPECT.cxx @@ -159,7 +159,9 @@ bool InterfilePDFSHeaderSPECT::post_processing() const int num_axial_blocks_per_bucket = -1; const int num_transaxial_blocks_per_bucket = -1; const int num_axial_crystals_per_block = -1; + const int num_virtual_axial_crystals_per_block=0; const int num_transaxial_crystals_per_block = -1; + const int num_virtual_transaxial_crystals_per_block = 0; const int num_axial_crystals_per_singles_unit = -1; const int num_transaxial_crystals_per_singles_unit = -1; const int num_detector_layers = 1; @@ -181,6 +183,8 @@ bool InterfilePDFSHeaderSPECT::post_processing() num_transaxial_blocks_per_bucket, num_axial_crystals_per_block, num_transaxial_crystals_per_block, + num_virtual_axial_crystals_per_block, + num_virtual_transaxial_crystals_per_block, num_axial_crystals_per_singles_unit, num_transaxial_crystals_per_singles_unit, num_detector_layers)); diff --git a/src/buildblock/Scanner.cxx b/src/buildblock/Scanner.cxx index 51a7a1301d..4accd5b51e 100644 --- a/src/buildblock/Scanner.cxx +++ b/src/buildblock/Scanner.cxx @@ -124,7 +124,7 @@ Scanner::Scanner(Type scanner_type) set_params(E931, string_list("ECAT 931"), 8, 192, 2 * 256, 510.0F, 7.0F, 13.5F, 3.129F, 0.0F, - 2, 4, 4, 8, 4, 8 * 4, 1, + 2, 4, 4, 8, 0, 0, 0, 0, 4, 8 * 4, 1, 0.37f, 511.f); // 16 BUCKETS per ring in TWO rings - i.e. 32 buckets in total @@ -135,7 +135,7 @@ Scanner::Scanner(Type scanner_type) set_params(E951, string_list("ECAT 951"), 16, 192, 2 * 256, 510.0F, 7.0F, 6.75F, 3.12932F, 0.0F, - 1, 4, 8, 8, 8, 8 * 4, 1); + 1, 4, 8, 8, 0, 0, 0, 0, 8, 8 * 4, 1); break; case E953: @@ -143,7 +143,7 @@ Scanner::Scanner(Type scanner_type) set_params(E953, string_list("ECAT 953"), 16, 160, 2 * 192, 382.5F, 7.0F, 6.75F, 3.12932F, static_cast(15.*_PI/180), - 1, 4, 8, 8, 8, 8 * 4, 1); + 1, 4, 8, 8, 0, 0, 0, 0, 8, 8 * 4, 1); break; case E921: @@ -151,7 +151,7 @@ Scanner::Scanner(Type scanner_type) set_params(E921, string_list("ECAT 921", "ECAT EXACT", "EXACT"), 24, 192, 2* 192, 412.5F, 7.0F, 6.75F, 3.375F, static_cast(15.*_PI/180), - 1, 4, 8, 8, 8, 8 * 4, 1); + 1, 4, 8, 8, 0, 0, 0, 0, 8, 8 * 4, 1); break; case E925: @@ -159,7 +159,7 @@ Scanner::Scanner(Type scanner_type) set_params(E925, string_list("ECAT 925", "ECAT ART"), 24, 192, 2* 192, 412.5F, 7.0F, 6.75F, 3.375F, static_cast(15.*_PI/180), - 3, 4, 8, 8, 8, 8 * 4, 1); + 3, 4, 8, 8, 0, 0, 0, 0, 8, 8 * 4, 1); break; @@ -168,7 +168,7 @@ Scanner::Scanner(Type scanner_type) set_params(E961,string_list("ECAT 961", "ECAT HR"), 24, 336, 2* 392, 412.0F, 7.0F, 6.25F, 1.650F, static_cast(13.*_PI/180), - 1, 8, 8, 7, 8, 7 * 8, 1); + 1, 8, 8, 7, 0, 0, 0, 0, 8, 7 * 8, 1); break; case E962: @@ -176,7 +176,7 @@ Scanner::Scanner(Type scanner_type) set_params(E962,string_list("ECAT 962","ECAT HR+"), 32, 288, 2* 288, 412.0F, 7.0F, 4.85F, 2.25F, 0.0F, - 4, 3, 8, 8, 8, 8 * 3, 1); + 4, 3, 8, 8, 0, 0, 0, 0, 8, 8 * 3, 1); break; case E966: @@ -184,15 +184,15 @@ Scanner::Scanner(Type scanner_type) set_params(E966, string_list("ECAT EXACT 3D", "EXACT 3D", "ECAT HR++","ECAT 966"), 48, 288, 2* 288, 412.0F, 7.0F, 4.850F, 2.250F, 0.0, - 6, 2, 8, 8, 2 * 8, 8 * 2, 1); + 6, 2, 8, 8, 0, 0, 0, 0, 2 * 8, 8 * 2, 1); break; case E1080: // data added by Robert Barnett, Westmead Hospital, Sydney set_params(E1080, string_list("ECAT 1080", "Biograph 16", "1080"), - 41, 336, 2* 336, + 39, 336, 13*48, 412.0F, 7.0F, 4.0F, 2.000F, 0.0F, - 1, 2, 13+1, 13+1, 0, 0, 1);// TODO bucket/singles info? + 1, 2, 13, 13, 1, 1, 0, 0, 0, 0, 1);// TODO bucket/singles info? // Transaxial blocks have 13 physical crystals and a gap at the // 14th crystal where the counts are zero. // There are 39 rings with 13 axial crystals per block. Two virtual @@ -206,16 +206,16 @@ Scanner::Scanner(Type scanner_type) set_params(Siemens_mMR, string_list("Siemens mMR", "mMR", "2008"), 64, 344, 2* 252, 328.0F, 7.0F, 4.0625F, 2.08626F, 0.0F, - 2, 1, 8, 9, 16, 9, 1, + 2, 1, 8, 9, 0, 0, 0, 0, 16, 9, 1, 0.145f, 511.f); // TODO bucket/singles info incorrect? 224 buckets in total, but not sure how distributed break; case Siemens_mCT: // 13x13 blocks, 1 virtual "crystal" along axial and transaxial direction, 48 blocks along the ring, 4 blocks in axial direction set_params(Siemens_mCT, string_list("Siemens mCT", "mCT", "2011", "1104" /* used in norm files */, "1094" /* used in attenuation files */), - 55, 400, (13+1)*48, + 52, 400, 13*48, 421.0F, 7.0F, 4.054F, 2.005F, 0.0F, - 4, 1, 13+1, 13+1, 0,0, 1 ); // TODO singles info incorrect + 4, 1, 13, 13, 1, 1, 0, 0, 0, 0, 1 ); // TODO singles info incorrect // energy: 435-650 // 13 TOF bins break; @@ -225,7 +225,7 @@ Scanner::Scanner(Type scanner_type) set_params(RPT, string_list("PRT-1", "RPT"), 16, 128, 2 * 192, 380.0F - 7.0F, 7.0F, 6.75F, 3.1088F, 0.0F, - 1, 4, 8, 8, 8, 32, 1); + 1, 4, 8, 8, 0, 0, 0, 0, 8, 32, 1); // Default 7.0mm average interaction depth. // This 7mm taken off the inner ring radius so that the effective radius remains 380mm @@ -236,7 +236,7 @@ Scanner::Scanner(Type scanner_type) set_params(RATPET, string_list("RATPET"), 8, 56, 2 * 56, 115 / 2.F, 7.0F, 6.25F, 1.65F, 0.0F, - 1, 16, 8, 7, 8, 0, 1); // HR block, 4 buckets per ring + 1, 16, 8, 7, 0, 0, 0, 0, 8, 0, 1); // HR block, 4 buckets per ring // Default 7.0mm average interaction depth. // 8 x 0 crystals per singles unit because not known @@ -248,7 +248,7 @@ Scanner::Scanner(Type scanner_type) set_params(PANDA, string_list("PANDA"), 1 /*NumRings*/, 512 /*MaxBinsNonArcCor*/, 512 /*MaxBinsArcCor*/, 2048 /*NumDetPerRing*/, /*MeanInnerRadius*/ 75.5/2.F, /*AverageDoI*/ 10.F, /*Ring Spacing*/ 3.F, /*BinSize*/ 0.1F, /*IntrinsicTilt*/ 0.F, - 1, 1, 1, 1, 0, 0, 1); + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1); break; case nanoPET: @@ -257,7 +257,7 @@ Scanner::Scanner(Type scanner_type) 81, 39*3, /* We could also model gaps in the future as one detector so 39->39+1, while 1 (point source), 3 (mouse) or 5 (rats) */ 39*3, /* Just put the same with NonArcCor for now*/ 12 * 39, 174.F, 5.0F, 1.17F, 1.17F, /* Actual size is 1.12 and 0.05 is the thickness of the optical reflector */ 0.0F, /* not sure for this */ - 0,0,0,0,0,0, 1); + 0,0,0,0,0,0, 0, 0, 0, 0, 1); break; case HYPERimage: @@ -265,7 +265,7 @@ Scanner::Scanner(Type scanner_type) set_params(HYPERimage, string_list("HYPERimage"), /*Modelling the gap with one fake crystal */ 22, 239, 245, 490, 103.97F, 3.0F, 1.4F, 1.4F, /* Actual size is 1.3667 and assume 0.0333 is the thickness of the optical reflector */ 0.F, - 0,0,0,0,0,0,1); + 0,0,0,0,0, 0,0, 0, 0,0,1); break; @@ -277,7 +277,7 @@ Scanner::Scanner(Type scanner_type) set_params(Advance, string_list("GE Advance", "Advance"), 18, 283, 281, 2 * 336, 471.875F - 8.4F, 8.4F, 8.5F, 1.970177F, 0.0F, //TODO view offset shouldn't be zero - 3, 2, 6, 6, 1, 1, 1); + 3, 2, 6, 6, 0, 0, 0, 0, 1, 1, 1); break; case DiscoveryLS: @@ -285,7 +285,7 @@ Scanner::Scanner(Type scanner_type) set_params(DiscoveryLS, string_list("GE Discovery LS", "Discovery LS"), 18, 283, 281, 2 * 336, 471.875F - 8.4F, 8.4F, 8.5F, 1.970177F, 0.0F, //TODO view offset shouldn't be zero - 3, 2, 6, 6, 1, 1, 1); + 3, 2, 6, 6, 0, 0, 0, 0, 1, 1, 1); break; case DiscoveryST: @@ -296,7 +296,7 @@ Scanner::Scanner(Type scanner_type) 24, 249, 221, 2 * 210, 886.2F/2.F, 8.4F, 6.54F, 3.195F, static_cast(-4.54224*_PI/180),//sign? - 4, 2, 6, 6, 1, 1, 1);// TODO not sure about sign of view_offset + 4, 2, 6, 6, 0, 0, 0, 0, 1, 1, 1);// TODO not sure about sign of view_offset break; case DiscoverySTE: @@ -305,7 +305,7 @@ Scanner::Scanner(Type scanner_type) 24, 329, 293, 2 * 280, 886.2F/2.F, 8.4F, 6.54F, 2.397F, static_cast(-4.5490*_PI/180),//sign? - 4, 2, 6, 8, 1, 1, 1);// TODO not sure about sign of view_offset + 4, 2, 6, 8, 0, 0, 0, 0, 1, 1, 1);// TODO not sure about sign of view_offset break; case DiscoveryRX: @@ -321,7 +321,7 @@ Scanner::Scanner(Type scanner_type) static_cast(-4.5950*_PI/180),//sign? 4, 2, - 6, 9, 1, 1, 1);// TODO not sure about sign of view_offset + 6, 9, 0, 0, 0, 0, 1, 1, 1);// TODO not sure about sign of view_offset break; case Discovery600: @@ -338,7 +338,7 @@ Scanner::Scanner(Type scanner_type) static_cast(-4.5490*_PI/180),//sign? TODO value 4, 2, - 6, 8, 1, 1, 1); + 6, 8, 0, 0, 0, 0, 1, 1, 1); break; @@ -356,7 +356,7 @@ case PETMR_Signa: static_cast(-5.23*_PI/180),//sign? TODO value 5, 4, - 9, 4, 1, 1, 1, + 9, 4, 0, 0, 0, 0, 1, 1, 1, 0.105F, // energy resolution from Levin et al. TMI 2016 511.F); break; @@ -376,7 +376,7 @@ break; static_cast(-5.021*_PI/180),//sign? TODO value 4, 2, - 6, 9, 1, 1, 1 + 6, 9, 0, 0, 0, 0, 1, 1, 1 #ifdef STIR_TOF , (short int)(55), @@ -403,6 +403,8 @@ break; static_cast(-4.399*_PI/180), //TODO check sign 3, 4, 9, 4, + 0, 0, + 0, 0, 1, 1, 1, 0.0944F, // energy resolution from Hsu et al. 2017 @@ -425,6 +427,8 @@ break; static_cast(-4.399*_PI/180), //TODO check sign 4, 4, 9, 4, + 0, 0, + 0, 0, 1, 1, 1, 0.0944F, // energy resolution from Hsu et al. 2017 @@ -436,7 +440,7 @@ break; set_params(HZLR, string_list("Positron HZL/R"), 32, 256, 2 * 192, 780.0F, 7.0F, 5.1875F, 2.F, 0.0F, - 0, 0, 0, 0, 0,0, 1); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); // Default 7.0mm average interaction depth. // crystals per singles unit etc unknown break; @@ -446,7 +450,7 @@ break; set_params(HRRT, string_list("HRRT"), 104, 288, 2 * 288, 234.765F, 7.0F, 2.4375F, 1.21875F, 0.0F, - 0, 0, 0, 0, 0, 0, 2); // added by Dylan Togane + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2); // added by Dylan Togane // warning: used 7.0mm average interaction depth. // crystals per singles unit etc unknown break; @@ -480,6 +484,8 @@ break; 6.3F, 4.3F, 0.0F, 1, 0, 29, 0 /* 23* or 22*/, + 0, 0, + 0, 0, 29, 0 /* all detectors in a ring? */, 1); break; @@ -492,7 +498,9 @@ break; 4.F, 4.F, 0.F, 0, 0, 0, 0, // Not considering any gap, but this is per module 28 flat modules in total, while 420 PMTs - 0, 0 /* Not sure about these, but shouldn't be important */, + 0, 0 /* Not sure about these, but shouldn't be important */, + 0, 0, + 0, 0, 1); break; @@ -500,7 +508,7 @@ break; set_params(HiDAC, string_list("HiDAC"), 0, 0, 0, 0.F, 0.F, 0.F, 0.F, 0.F, - 0, 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break; @@ -509,7 +517,7 @@ break; set_params(User_defined_scanner, string_list("Userdefined"), 0, 0, 0, 0.F, 0.F, 0.F, 0.F, 0.F, - 0, 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break; @@ -518,7 +526,7 @@ break; set_params(Unknown_scanner, string_list("Unknown"), 0, 0, 0, 0.F, 0.F, 0.F, 0.F, 0.F, - 0, 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); break; @@ -535,6 +543,8 @@ Scanner::Scanner(Type type_v, const list& list_of_names_v, float ring_spacing_v, float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -550,6 +560,8 @@ Scanner::Scanner(Type type_v, const list& list_of_names_v, ring_spacing_v, bin_size_v, intrinsic_tilt_v, num_axial_blocks_per_bucket_v, num_transaxial_blocks_per_bucket_v, num_axial_crystals_per_block_v, num_transaxial_crystals_per_block_v, + num_virtual_axial_crystals_per_block_v, num_virtual_transaxial_crystals_per_block_v, + num_virtual_axial_crystals_per_bucket_v, num_virtual_transaxial_crystals_per_bucket_v, num_axial_crystals_per_singles_unit_v, num_transaxial_crystals_per_singles_unit_v, num_detector_layers_v, @@ -567,6 +579,8 @@ Scanner::Scanner(Type type_v, const string& name, float ring_spacing_v, float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -582,6 +596,8 @@ Scanner::Scanner(Type type_v, const string& name, ring_spacing_v, bin_size_v, intrinsic_tilt_v, num_axial_blocks_per_bucket_v, num_transaxial_blocks_per_bucket_v, num_axial_crystals_per_block_v, num_transaxial_crystals_per_block_v, + num_virtual_axial_crystals_per_block_v, num_virtual_transaxial_crystals_per_block_v, + num_virtual_axial_crystals_per_bucket_v, num_virtual_transaxial_crystals_per_bucket_v, num_axial_crystals_per_singles_unit_v, num_transaxial_crystals_per_singles_unit_v, num_detector_layers_v, @@ -607,6 +623,8 @@ set_params(Type type_v,const list& list_of_names_v, float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -622,6 +640,8 @@ set_params(Type type_v,const list& list_of_names_v, ring_spacing_v, bin_size_v, intrinsic_tilt_v, num_axial_blocks_per_bucket_v, num_transaxial_blocks_per_bucket_v, num_axial_crystals_per_block_v, num_transaxial_crystals_per_block_v, + num_virtual_axial_crystals_per_block_v, num_virtual_transaxial_crystals_per_block_v, + num_virtual_axial_crystals_per_bucket_v, num_virtual_transaxial_crystals_per_bucket_v, num_axial_crystals_per_singles_unit_v, num_transaxial_crystals_per_singles_unit_v, num_detector_layers_v, @@ -643,6 +663,8 @@ set_params(Type type_v,const list& list_of_names_v, float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -664,6 +686,10 @@ set_params(Type type_v,const list& list_of_names_v, num_axial_blocks_per_bucket = num_axial_blocks_per_bucket_v; num_axial_crystals_per_block= num_axial_crystals_per_block_v; num_transaxial_crystals_per_block= num_transaxial_crystals_per_block_v; + num_virtual_axial_crystals_per_block= num_virtual_axial_crystals_per_block_v; + num_virtual_transaxial_crystals_per_block= num_virtual_transaxial_crystals_per_block_v; + num_virtual_axial_crystals_per_bucket = num_virtual_axial_crystals_per_bucket_v; + num_virtual_transaxial_crystals_per_bucket = num_virtual_transaxial_crystals_per_bucket_v; num_axial_crystals_per_singles_unit = num_axial_crystals_per_singles_unit_v; num_transaxial_crystals_per_singles_unit = num_transaxial_crystals_per_singles_unit_v; num_detector_layers = num_detector_layers_v; @@ -676,56 +702,47 @@ set_params(Type type_v,const list& list_of_names_v, } -/*! \todo The current list is bound to be incomplete. would be better to stick it in set_params(). - */ int Scanner:: get_num_virtual_axial_crystals_per_block() const { - switch(get_type()) - { - case E1080: - case Siemens_mCT: - return 1; - default: - return 0; - } + return num_virtual_axial_crystals_per_block; } -/*! \todo The current list is bound to be incomplete. would be better to stick it in set_params(). - */ int Scanner:: get_num_virtual_transaxial_crystals_per_block() const { - switch(get_type()) - { - case E1080: - case Siemens_mCT: - case Siemens_mMR: - return 1; - default: - return 0; - } + return num_virtual_transaxial_crystals_per_block; +} + +int +Scanner:: +get_num_virtual_axial_crystals_per_bucket() const +{ + return num_virtual_axial_crystals_per_bucket; +} + +int +Scanner:: +get_num_virtual_transaxial_crystals_per_bucket() const +{ + return num_virtual_transaxial_crystals_per_bucket; } -/*! \todo Can currently only set to hard-wired values. Otherwise calls error() */ + void Scanner:: set_num_virtual_axial_crystals_per_block(int val) { - //num_virtual_axial_crystals_per_block = val; - if (this->get_num_virtual_axial_crystals_per_block() != val) - error("Scanner::set_num_virtual_axial_crystals_per_block not really implemented yet"); + num_virtual_axial_crystals_per_block = val; } -/*! \todo Can currently only set to hard-wired values. Otherwise calls error() */ + void Scanner:: set_num_virtual_transaxial_crystals_per_block(int val) { - //num_virtual_transaxial_crystals_per_block = val; - if (this->get_num_virtual_transaxial_crystals_per_block() != val) - error("Scanner::set_num_virtual_transaxial_crystals_per_block not really implemented yet"); + num_virtual_transaxial_crystals_per_block = val; } @@ -744,14 +761,15 @@ check_consistency() const this->get_name().c_str()); else { - const int dets_per_ring = - get_num_transaxial_blocks() * - get_num_transaxial_crystals_per_block(); - if ( dets_per_ring != get_num_detectors_per_ring()) - { - warning("Scanner %s: inconsistent transaxial block info", - this->get_name().c_str()); - return Succeeded::no; + const int dets_per_ring = + get_num_transaxial_buckets() * get_num_transaxial_blocks_per_bucket() * + get_num_transaxial_crystals_per_block()+ + get_num_transaxial_buckets()*get_num_virtual_transaxial_crystals_per_bucket(); + if ( dets_per_ring != get_num_detectors_per_ring()) + { + warning("Scanner %s: inconsistent transaxial block info %d instead of %d", + this->get_name().c_str(), dets_per_ring, get_num_detectors_per_ring()); + return Succeeded::no; } } } @@ -781,13 +799,13 @@ check_consistency() const else { const int dets_axial = - get_num_axial_blocks() * - get_num_axial_crystals_per_block(); - if ( dets_axial != (get_num_rings() + get_num_virtual_axial_crystals_per_block())) + get_num_axial_buckets() * get_num_axial_blocks_per_bucket() * + get_num_axial_crystals_per_block() + get_num_axial_buckets()*get_num_virtual_axial_crystals_per_bucket(); + if ( dets_axial != get_num_rings()) { warning("Scanner %s: inconsistent axial block info: %d vs %d", this->get_name().c_str(), - dets_axial, get_num_rings() + get_num_virtual_axial_crystals_per_block()); + dets_axial, get_num_rings()); return Succeeded::no; } } @@ -817,12 +835,12 @@ check_consistency() const this->get_name().c_str()); else { - if ( get_num_detectors_per_ring() % get_num_transaxial_crystals_per_singles_unit() != 0) + if ( get_num_detectors_per_ring() % (get_num_transaxial_crystals_per_singles_unit() + get_num_virtual_transaxial_crystals_per_block()) != 0) { warning("Scanner %s: inconsistent transaxial singles unit info:\n" - "\tnum_detectors_per_ring %d should be a multiple of num_transaxial_crystals_per_singles_unit %d", + "\tnum_detectors_per_ring %d should be a multiple of num_transaxial_crystals_per_singles_unit + virtual %d", this->get_name().c_str(), - get_num_detectors_per_ring(), get_num_transaxial_crystals_per_singles_unit()); + get_num_detectors_per_ring(), (get_num_transaxial_crystals_per_singles_unit() + get_num_virtual_transaxial_crystals_per_block())); return Succeeded::no; } if ( get_num_transaxial_crystals_per_bucket() % get_num_transaxial_crystals_per_singles_unit() != 0) @@ -898,6 +916,10 @@ if (!close_enough(energy_resolution, scanner.energy_resolution) && (num_axial_blocks_per_bucket == scanner.num_axial_blocks_per_bucket) && (num_axial_crystals_per_block == scanner.num_axial_crystals_per_block) && (num_transaxial_crystals_per_block == scanner.num_transaxial_crystals_per_block) && + (num_virtual_axial_crystals_per_block == scanner.num_virtual_axial_crystals_per_block) && + (num_virtual_transaxial_crystals_per_block == scanner.num_virtual_transaxial_crystals_per_block) && + (num_virtual_axial_crystals_per_bucket == scanner.num_virtual_axial_crystals_per_bucket) && + (num_virtual_transaxial_crystals_per_bucket == scanner.num_virtual_transaxial_crystals_per_bucket) && (num_detector_layers == scanner.num_detector_layers) && (num_axial_crystals_per_singles_unit == scanner.num_axial_crystals_per_singles_unit) && (num_transaxial_crystals_per_singles_unit == scanner.num_transaxial_crystals_per_singles_unit); @@ -934,7 +956,7 @@ Scanner::parameter_info() const s << "Scanner type := " << get_name() <<'\n'; s << "Number of rings := " << num_rings << '\n'; - s << "Number of detectors per ring := " << get_num_detectors_per_ring() << '\n'; + s << "Number of detectors per ring := " << num_detectors_per_ring << '\n'; s << "Inner ring diameter (cm) := " << get_inner_ring_radius()*2./10 << '\n' << "Average depth of interaction (cm) := " << get_average_depth_of_interaction() / 10 << '\n' @@ -957,9 +979,17 @@ Scanner::parameter_info() const << "Number of blocks per bucket in axial direction := " << get_num_axial_blocks_per_bucket() << '\n' << "Number of crystals per block in axial direction := " - << get_num_axial_crystals_per_block() << '\n' + << num_axial_crystals_per_block << '\n' << "Number of crystals per block in transaxial direction := " - << get_num_transaxial_crystals_per_block() << '\n' + << num_transaxial_crystals_per_block << '\n' + << "Number of Virtual crystals per block in axial direction := " + << get_num_virtual_axial_crystals_per_block() << '\n' + << "Number of Virtual crystals per block in transaxial direction := " + << get_num_virtual_transaxial_crystals_per_block() << '\n' + << "Number of Virtual crystals per bucket in axial direction := " + << get_num_virtual_axial_crystals_per_bucket() << '\n' + << "Number of Virtual crystals per bucket in transaxial direction := " + << get_num_virtual_transaxial_crystals_per_bucket() << '\n' << "Number of detector layers := " << get_num_detector_layers() << '\n' << "Number of crystals per singles unit in axial direction := " @@ -1061,6 +1091,14 @@ Scanner* Scanner::ask_parameters() ask_num("Enter number of axial crystals per block: ",0,12,8); int TransaxialCrystalsPerBlock = ask_num("Enter number of transaxial crystals per block: ",0,12,8); + int VirtualAxialCrystalsPerBlock = + ask_num("Enter number of virtual axial crystals per block: ",0,12,0); + int VirtualTransaxialCrystalsPerBlock = + ask_num("Enter number of virtual transaxial crystals per block: ",0,12,0); + int VirtualAxialCrystalsPerBucket = + ask_num("Enter number of virtual axial crystals per bucket: ",0,12,0); + int VirtualTransaxialCrystalsPerBucket = + ask_num("Enter number of virtual transaxial crystals per bucket: ",0,12,0); int AxialCrstalsPerSinglesUnit = ask_num("Enter number of axial crystals per singles unit: ", 0, NoRings, 1); int TransaxialCrystalsPerSinglesUnit = @@ -1085,6 +1123,8 @@ Scanner* Scanner::ask_parameters() RingSpacing, BinSize,intrTilt*float(_PI)/180, AxialBlocksPerBucket,TransBlocksPerBucket, AxialCrystalsPerBlock,TransaxialCrystalsPerBlock, + VirtualAxialCrystalsPerBlock, VirtualTransaxialCrystalsPerBlock, + VirtualAxialCrystalsPerBucket, VirtualTransaxialCrystalsPerBucket, AxialCrstalsPerSinglesUnit, TransaxialCrystalsPerSinglesUnit, num_detector_layers, EnergyResolution, @@ -1098,6 +1138,8 @@ Scanner* Scanner::ask_parameters() RingSpacing, BinSize,intrTilt*float(_PI)/180, AxialBlocksPerBucket,TransBlocksPerBucket, AxialCrystalsPerBlock,TransaxialCrystalsPerBlock, + VirtualAxialCrystalsPerBlock, VirtualTransaxialCrystalsPerBlock, + VirtualAxialCrystalsPerBucket, VirtualTransaxialCrystalsPerBucket, AxialCrstalsPerSinglesUnit, TransaxialCrystalsPerSinglesUnit, num_detector_layers); diff --git a/src/include/stir/IO/InterfileHeader.h b/src/include/stir/IO/InterfileHeader.h index 271c2ad380..bf667c7ef1 100644 --- a/src/include/stir/IO/InterfileHeader.h +++ b/src/include/stir/IO/InterfileHeader.h @@ -284,6 +284,8 @@ class InterfilePDFSHeader : public InterfileHeader int num_transaxial_blocks_per_bucket; int num_axial_crystals_per_block; int num_transaxial_crystals_per_block; + int num_virtual_axial_crystals_per_block; + int num_virtual_transaxial_crystals_per_block; int num_axial_crystals_per_singles_unit; int num_transaxial_crystals_per_singles_unit; int num_detector_layers; diff --git a/src/include/stir/Scanner.h b/src/include/stir/Scanner.h index 6780bcc4cf..68a25eddce 100644 --- a/src/include/stir/Scanner.h +++ b/src/include/stir/Scanner.h @@ -116,7 +116,7 @@ class Scanner to flag up an error and do some guess work in trying to recognise the scanner from any given parameters. */ - enum Type {E931, E951, E953, E921, E925, E961, E962, E966, E1080, Siemens_mMR,Siemens_mCT, RPT,HiDAC, + enum Type {E931, Siemens_mCT, E951, E953, E921, E925, E961, E962, E966, E1080, Siemens_mMR, RPT,HiDAC, Advance, DiscoveryLS, DiscoveryST, DiscoverySTE, DiscoveryRX, Discovery600, PETMR_Signa, Discovery690, DiscoveryMI3ring, DiscoveryMI4ring, HZLR, RATPET, PANDA, HYPERimage, nanoPET, HRRT, Allegro, GeminiTF, User_defined_scanner, Unknown_scanner}; @@ -138,6 +138,8 @@ class Scanner float ring_spacing_v, float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -157,6 +159,8 @@ class Scanner float ring_spacing_v, float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -188,9 +192,10 @@ class Scanner //! \name Functions returning geometrical info //@{ - //! get number of rings + //! get number of rings. This function returns the total number of rings + gaps inline int get_num_rings() const; - //! get the number of detectors per ring + //! get the number of detectors per ring. This function returns the total + //! number of detectors + gasp in the ring. inline int get_num_detectors_per_ring() const; //! get the maximum number of arccorrected tangential positions /*! \warning name is not in standard STIR terminology. Should be @@ -278,6 +283,10 @@ class Scanner //@{! int get_num_virtual_axial_crystals_per_block() const; int get_num_virtual_transaxial_crystals_per_block() const; + + int get_num_virtual_axial_crystals_per_bucket() const; + int get_num_virtual_transaxial_crystals_per_bucket() const; + void set_num_virtual_axial_crystals_per_block(int); void set_num_virtual_transaxial_crystals_per_block(int); //@} @@ -302,9 +311,11 @@ class Scanner // zlong, 08-04-2004, add set_methods //! set scanner type inline void set_type(const Type & new_type); - //! set number of rings + //! set number of rings. This function will set the total number of rings + //! reseting the virtual crystals to the axial direction to 0. inline void set_num_rings(const int & new_num); - //! set the namber of detectors per ring + //! set the namber of detectors per ring. This function will set the total number + //! of detectors per ring, reseting the number of virtual crystals to 0. inline void set_num_detectors_per_ring(const int & new_num) ; //! set the maximum number of arccorrected bins inline void set_max_num_non_arccorrected_bins(const int & new_num) ; @@ -383,11 +394,19 @@ class Scanner int num_axial_blocks_per_bucket; /* axial blocks per bucket */ int num_axial_crystals_per_block; /* number of crystals in the axial direction */ int num_transaxial_crystals_per_block;/* number of transaxial crystals */ + //! Number of axial virtual crystals per block + int num_virtual_axial_crystals_per_block; + //! Number of transaxial virtual crystals per block + int num_virtual_transaxial_crystals_per_block; int num_detector_layers; int num_axial_crystals_per_singles_unit; int num_transaxial_crystals_per_singles_unit; + int num_virtual_axial_crystals_per_bucket; + + int num_virtual_transaxial_crystals_per_bucket; + //! //! \brief energy_resolution //! \author Nikos Efthimiou @@ -415,6 +434,8 @@ class Scanner float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, @@ -433,6 +454,8 @@ class Scanner float bin_size_v, float intrinsic_tilt_v, int num_axial_blocks_per_bucket_v, int num_transaxial_blocks_per_bucket_v, int num_axial_crystals_per_block_v, int num_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_block_v, int num_virtual_transaxial_crystals_per_block_v, + int num_virtual_axial_crystals_per_bucket_v, int num_virtual_transaxial_crystals_per_bucket_v, int num_axial_crystals_per_singles_unit_v, int num_transaxial_crystals_per_singles_unit_v, int num_detector_layers_v, diff --git a/src/include/stir/Scanner.inl b/src/include/stir/Scanner.inl index 4ce80d1c20..e2c8935efb 100644 --- a/src/include/stir/Scanner.inl +++ b/src/include/stir/Scanner.inl @@ -46,11 +46,17 @@ Scanner::get_type() const int Scanner::get_num_rings() const -{ return num_rings;} +{ + return num_rings + get_num_virtual_axial_crystals_per_bucket() * get_num_axial_buckets() + + get_num_virtual_axial_crystals_per_block() * get_num_axial_blocks(); +} int Scanner::get_num_detectors_per_ring() const { - return num_detectors_per_ring;} + return num_detectors_per_ring + get_num_virtual_transaxial_crystals_per_bucket() * get_num_transaxial_buckets() + + get_num_virtual_transaxial_crystals_per_block() * get_num_transaxial_blocks(); +} + int Scanner::get_max_num_non_arccorrected_bins() const { return max_num_non_arccorrected_bins;} @@ -116,13 +122,15 @@ Scanner::get_num_axial_blocks_per_bucket() const int Scanner::get_num_axial_crystals_per_block() const { - return num_axial_crystals_per_block; + return num_axial_crystals_per_block + + get_num_virtual_axial_crystals_per_block(); } int Scanner::get_num_transaxial_crystals_per_block()const { - return num_transaxial_crystals_per_block; + return (num_transaxial_crystals_per_block + + get_num_virtual_transaxial_crystals_per_block()); } @@ -131,7 +139,8 @@ Scanner::get_num_axial_crystals_per_bucket() const { return get_num_axial_blocks_per_bucket() * - get_num_axial_crystals_per_block(); + get_num_axial_crystals_per_block() + + get_num_virtual_axial_crystals_per_bucket(); } @@ -140,7 +149,8 @@ Scanner::get_num_transaxial_crystals_per_bucket() const { return get_num_transaxial_blocks_per_bucket() * - get_num_transaxial_crystals_per_block(); + get_num_transaxial_crystals_per_block() + + get_num_virtual_transaxial_crystals_per_bucket(); } int @@ -154,25 +164,28 @@ Scanner::get_num_axial_blocks() const { // when using virtual crystals between blocks, there won't be one at the end, so we // need to take this into account. - return (num_rings+get_num_virtual_axial_crystals_per_block())/num_axial_crystals_per_block; + return (num_rings)/num_axial_crystals_per_block; } int Scanner::get_num_transaxial_blocks() const { - return num_detectors_per_ring/num_transaxial_crystals_per_block; + return num_transaxial_crystals_per_block == 0 ? num_detectors_per_ring : + num_detectors_per_ring/(num_transaxial_crystals_per_block); } int Scanner::get_num_axial_buckets() const { - return get_num_axial_blocks()/num_axial_blocks_per_bucket; + return num_axial_blocks_per_bucket == 0 ? get_num_axial_blocks() : + get_num_axial_blocks()/num_axial_blocks_per_bucket; } int Scanner::get_num_transaxial_buckets() const { - return get_num_transaxial_blocks()/num_transaxial_blocks_per_bucket; + return num_transaxial_blocks_per_bucket== 0 ? get_num_transaxial_blocks() : + get_num_transaxial_blocks()/num_transaxial_blocks_per_bucket; } @@ -240,11 +253,15 @@ void Scanner::set_type(const Type & new_type) void Scanner::set_num_rings(const int & new_num) { + num_virtual_axial_crystals_per_bucket = 0; + num_virtual_axial_crystals_per_block = 0; num_rings = new_num; } -void Scanner::set_num_detectors_per_ring(const int & new_num) +void Scanner::set_num_detectors_per_ring(const int & new_num) { + num_virtual_transaxial_crystals_per_bucket = 0; + num_virtual_transaxial_crystals_per_block = 0; num_detectors_per_ring = new_num; } diff --git a/src/listmode_buildblock/CListModeDataROOT.cxx b/src/listmode_buildblock/CListModeDataROOT.cxx index 6bd87b0dce..46cc03e56c 100644 --- a/src/listmode_buildblock/CListModeDataROOT.cxx +++ b/src/listmode_buildblock/CListModeDataROOT.cxx @@ -46,6 +46,8 @@ CListModeDataROOT(const std::string& hroot_filename) std::string error_str; int num_virtual_axial_crystals_per_block = -1; // -1 means: use scanner default int num_virtual_transaxial_crystals_per_block = -1; // -1 means: use scanner default + int num_virtual_axial_crystals_per_bucket = -1; // -1 means: use scanner default + int num_virtual_transaxial_crystals_per_bucket = -1; // -1 means: use scanner default this->parser.add_start_key("ROOT header"); this->parser.add_stop_key("End ROOT header"); @@ -64,6 +66,8 @@ CListModeDataROOT(const std::string& hroot_filename) this->parser.add_key("Default number of arc-corrected bins", &this->default_num_arccorrected_bins); this->parser.add_key("Number of virtual axial crystals per block", &num_virtual_axial_crystals_per_block); this->parser.add_key("Number of virtual transaxial crystals per block", &num_virtual_transaxial_crystals_per_block); + this->parser.add_key("Number of virtual axial crystals per bucket", &num_virtual_axial_crystals_per_bucket); + this->parser.add_key("Number of virtual transaxial crystals per bucket", &num_virtual_transaxial_crystals_per_bucket); // end Scanner and physical dimensions. // ROOT related @@ -145,17 +149,17 @@ CListModeDataROOT(const std::string& hroot_filename) this->root_file_sptr->get_num_axial_crystals_per_block_v(), /*num_transaxial_crystals_per_block_v*/ this->root_file_sptr->get_num_transaxial_crystals_per_block_v(), + num_virtual_axial_crystals_per_block, + num_virtual_transaxial_crystals_per_block, + num_virtual_axial_crystals_per_bucket, + num_virtual_transaxial_crystals_per_bucket, /*num_axial_crystals_per_singles_unit_v*/ this->root_file_sptr->get_num_axial_crystals_per_singles_unit(), /*num_transaxial_crystals_per_singles_unit_v*/ this->root_file_sptr->get_num_trans_crystals_per_singles_unit(), /*num_detector_layers_v*/ 1 )); } - // have to do this here currently as these variables cannot be set via the constructor - if (num_virtual_axial_crystals_per_block>=0) - this_scanner_sptr->set_num_virtual_axial_crystals_per_block(num_virtual_axial_crystals_per_block); - if (num_virtual_transaxial_crystals_per_block>=0) - this_scanner_sptr->set_num_virtual_transaxial_crystals_per_block(num_virtual_transaxial_crystals_per_block); + // put virtual block info in root_file_sptr this->root_file_sptr->set_num_virtual_axial_crystals_per_block(this_scanner_sptr->get_num_virtual_axial_crystals_per_block()); this->root_file_sptr->set_num_virtual_transaxial_crystals_per_block(this_scanner_sptr->get_num_virtual_transaxial_crystals_per_block()); @@ -263,37 +267,45 @@ check_scanner_match_geometry(std::string& ret, const shared_ptr& scanne if (scanner_sptr->get_num_rings() != root_file_sptr->get_num_rings()) { - stream << "the number of rings, "; + stream << "the number of rings ("<< scanner_sptr->get_num_rings() << ", " << + root_file_sptr->get_num_rings() << "), "; ok = false; } - if (scanner_sptr->get_num_detectors_per_ring() != root_file_sptr->get_num_dets_per_ring()) + if ((scanner_sptr->get_num_detectors_per_ring() - scanner_sptr->get_num_virtual_transaxial_crystals()) != root_file_sptr->get_num_dets_per_ring()) { - stream << "the number of detector per ring, "; + stream << "the number of detector per ring ("<< (scanner_sptr->get_num_detectors_per_ring() - scanner_sptr->get_num_virtual_transaxial_crystals()) << ", " << + root_file_sptr->get_num_dets_per_ring() << "), "; ok = false; } if (scanner_sptr->get_num_axial_blocks_per_bucket() != root_file_sptr->get_num_axial_blocks_per_bucket_v()) { - stream << "the number of axial blocks per bucket, "; + stream << "the number of axial blocks per bucket ("<< scanner_sptr->get_num_axial_blocks_per_bucket() << ", " << + root_file_sptr->get_num_axial_blocks_per_bucket_v() << "), "; ok = false; } if(scanner_sptr->get_num_transaxial_blocks_per_bucket() != root_file_sptr->get_num_transaxial_blocks_per_bucket_v()) { - stream << "the number of transaxial blocks per bucket, "; + stream << "the number of transaxial blocks per bucket ("<< scanner_sptr->get_num_transaxial_blocks_per_bucket() << ", " << + root_file_sptr->get_num_transaxial_blocks_per_bucket_v() << "), "; ok = false; } - if(scanner_sptr->get_num_axial_crystals_per_block() != root_file_sptr->get_num_axial_crystals_per_block_v()) + if((scanner_sptr->get_num_axial_crystals_per_block() + + scanner_sptr->get_num_virtual_axial_crystals_per_block()) != root_file_sptr->get_num_axial_crystals_per_block_v()) { - stream << "the number of axial crystals per block, "; + stream << "the number of axial crystals per block ("<< scanner_sptr->get_num_axial_crystals_per_block() << ", " << + root_file_sptr->get_num_axial_crystals_per_block_v() << "), "; ok = false; } - if(scanner_sptr->get_num_transaxial_crystals_per_block() != root_file_sptr->get_num_transaxial_crystals_per_block_v()) + if((scanner_sptr->get_num_transaxial_crystals_per_block() + + scanner_sptr->get_num_virtual_transaxial_crystals_per_block())!= root_file_sptr->get_num_transaxial_crystals_per_block_v()) { - stream << "the number of transaxial crystals per block, "; + stream << "the number of transaxial crystals per block ("<< scanner_sptr->get_num_transaxial_crystals_per_block() << ", " << + root_file_sptr->get_num_transaxial_crystals_per_block_v() << "), "; ok = false; } @@ -305,7 +317,8 @@ check_scanner_match_geometry(std::string& ret, const shared_ptr& scanne if(scanner_sptr->get_num_transaxial_crystals_per_singles_unit() != root_file_sptr->get_num_trans_crystals_per_singles_unit()) { - stream << "the number of transaxial crystals per singles unit, "; + stream << "the number of transaxial crystals per singles unit ("<< scanner_sptr->get_num_transaxial_crystals_per_singles_unit() << ", " << + root_file_sptr->get_num_trans_crystals_per_singles_unit() << "), "; ok = false; }