Skip to content

Commit 42bf1e9

Browse files
committed
shifting the first detector index to the first crystal in the firts bucket
1 parent 7ec9546 commit 42bf1e9

4 files changed

+85
-50
lines changed

src/buildblock/GeometryBlocksOnCylindrical.cxx

100644100755
+19-16
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,22 @@ build_crystal_maps()
169169
see start_x*/
170170

171171
//calculate start_point to build the map.
172+
173+
// estimate the angle covered by half bucket, csi
174+
float csi=_PI/num_transaxial_buckets;
175+
float trans_blocks_gap=transaxial_block_spacing-num_transaxial_crystals_per_block*transaxial_crystal_spacing;
176+
float csi_minus_csiGaps=csi-(csi/transaxial_block_spacing*2)*
177+
(transaxial_crystal_spacing/2+trans_blocks_gap);
178+
// distance between the center of the scannner and the first crystal in the bucket, r=Reffective/cos(csi)
179+
float r=get_scanner_ptr()->get_effective_ring_radius()/cos(csi_minus_csiGaps);
180+
172181
float start_z = 0;
173182
float start_y = -1*get_scanner_ptr()->get_effective_ring_radius();
174-
float start_x = -1*(
175-
((num_transaxial_blocks_per_bucket-1)/2.)*transaxial_block_spacing
176-
+ ((num_transaxial_crystals_per_block-1)/2.)*transaxial_crystal_spacing
177-
); //the first crystal in the bucket
183+
float start_x = -1*r*sin(csi_minus_csiGaps);//(
184+
// ((num_transaxial_blocks_per_bucket-1)/2.)*transaxial_block_spacing
185+
// + ((num_transaxial_crystals_per_block-1)/2.)*transaxial_crystal_spacing
186+
// ); //the first crystal in the bucket
187+
178188
stir::CartesianCoordinate3D<float> start_point(start_z, start_y, start_x);
179189

180190
for (int ax_block_num=0; ax_block_num<num_axial_blocks; ++ax_block_num)
@@ -184,20 +194,12 @@ build_crystal_maps()
184194
for (int trans_crys_num=0; trans_crys_num<num_transaxial_crystals_per_block; ++trans_crys_num)
185195
{
186196
// calculate detection position for a given detector
187-
// note: in STIR convention, crystal(0,0,0) corresponds to card_coord(z=-l/2,y=-r,x=0)
197+
// note: in STIR convention, crystal(0,0,0) corresponds to card_coord(z=0,y=-r,x=0)
188198
int tangential_coord;
189-
if (num_transaxial_blocks_per_bucket%2==0)
190199
tangential_coord = trans_bucket_num*num_transaxial_blocks_per_bucket*num_transaxial_crystals_per_block
191200
+ trans_block_num*num_transaxial_crystals_per_block
192-
+ trans_crys_num
193-
- num_transaxial_blocks_per_bucket/2*num_transaxial_crystals_per_block;
194-
else
195-
tangential_coord = trans_bucket_num*num_transaxial_blocks_per_bucket*num_transaxial_crystals_per_block
196-
+ trans_block_num*num_transaxial_crystals_per_block
197-
+ trans_crys_num
198-
- num_transaxial_blocks_per_bucket/2*num_transaxial_crystals_per_block
199-
- num_transaxial_crystals_per_block/2;
200-
201+
+ trans_crys_num;
202+
201203
if (tangential_coord<0)
202204
tangential_coord += num_detectors_per_ring;
203205

@@ -210,7 +212,8 @@ build_crystal_maps()
210212
ax_block_num*axial_block_spacing + ax_crys_num*axial_crystal_spacing,
211213
0.,
212214
trans_block_num*transaxial_block_spacing + trans_crys_num*transaxial_crystal_spacing);
213-
float alpha = trans_bucket_num*(2*_PI)/num_transaxial_buckets;
215+
float alpha = get_scanner_ptr()->get_intrinsic_azimuthal_tilt()+
216+
trans_bucket_num*(2*_PI)/num_transaxial_buckets+csi_minus_csiGaps;
214217

215218
stir::Array<2, float> rotation_matrix = get_rotation_matrix(alpha);
216219
// to match index range of CartesianCoordinate3D, which is 1 to 3

src/buildblock/ProjDataInfoGeneric.cxx

100644100755
+1-1
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ get_LOR(LORInAxialAndNoArcCorrSinogramCoordinates<float>& lor,
499499
find_cartesian_coordinates_of_detection(_p1, _p2, bin);
500500

501501
LORAs2Points<float> lor_as_2_points(_p1, _p2);
502-
const double R = get_ring_radius();
502+
const double R = sqrt(max(square(_p1.x())+square(_p1.y()), square(_p2.x())+square(_p2.y())));
503503

504504
lor_as_2_points.change_representation(lor, R);
505505
}

src/recon_test/test_blocks_on_cylindrical_projectors.cxx

100644100755
+22-12
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,22 @@ BlocksTests::run_plane_symmetry_test(){
106106

107107
// rotate by 30 degrees
108108
phi2=30*_PI/180;
109-
VoxelsOnCartesianGrid<float> image2=image;
109+
VoxelsOnCartesianGrid<float> image2=*image.get_empty_copy();
110110
const Array<2,float> direction2=make_array(make_1d_array(1.F,0.F,0.F),
111111
make_1d_array(0.F,cos(float(_PI)-phi2),sin(float(_PI)-phi2)),
112112
make_1d_array(0.F,-sin(float(_PI)-phi2),cos(float(_PI)-phi2)));
113-
plane.set_direction_vectors(direction2);
113+
114+
Ellipsoid
115+
plane2(CartesianCoordinate3D<float>(/*edge_z*/25*grid_spacing.z(),
116+
/*edge_y*/91*grid_spacing.y(),
117+
/*edge_x*/5*grid_spacing.x()),
118+
/*centre*/CartesianCoordinate3D<float>((image.get_min_index()+image.get_max_index())/2*grid_spacing.z(),
119+
0*grid_spacing.y(),
120+
0),
121+
direction2);
122+
// plane.set_direction_vectors(direction2);
114123

115-
plane.construct_volume(image2, make_coordinate(3,3,3));
124+
plane2.construct_volume(image2, make_coordinate(3,3,3));
116125

117126
// create projadata info
118127

@@ -196,20 +205,21 @@ BlocksTests::run_plane_symmetry_test(){
196205
forw_projector2_sptr->forward_project(*projdata2, *image2_sptr);
197206

198207
int view1_num = 0, view2_num = 0;
199-
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorB;
208+
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorB1;
200209
for(int i=0;i<projdata->get_max_view_num();i++){
201210
Bin bin(0,i,0,0);
202-
proj_data_info_blocks_ptr->get_LOR(lorB,bin);
203-
if(abs(lorB.phi()-phi1)/phi1<=1E-2){
211+
proj_data_info_blocks_ptr->get_LOR(lorB1,bin);
212+
if(abs(lorB1.phi()-phi1)/phi1<=1E-2){
204213
view1_num=i;
205214
break;
206215
}
207216
}
208217

218+
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorB2;
209219
for(int i=0;i<projdata2->get_max_view_num();i++){
210220
Bin bin(0,i,0,0);
211-
proj_data_info_blocks_ptr->get_LOR(lorB,bin);
212-
if(abs(lorB.phi()-phi2)/phi2<=1E-2){
221+
proj_data_info_blocks_ptr->get_LOR(lorB2,bin);
222+
if(abs(lorB2.phi()-phi2)/phi2<=1E-2){
213223
view2_num=i;
214224
break;
215225
}
@@ -231,16 +241,16 @@ BlocksTests::run_plane_symmetry_test(){
231241
for(int tang=projdata2->get_min_tangential_pos_num();tang<projdata2->get_max_tangential_pos_num();tang++){
232242

233243
if((max2-projdata2->get_sinogram(0,0).at(view2_num).at(tang))/max2<1E-3) {
234-
tang1_num=tang;
244+
tang2_num=tang;
235245
break;
236246
}
237247
}
238248

239249
float bin1=projdata->get_sinogram(0,0).at(view1_num).at(tang1_num);
240250
float bin2=projdata2->get_sinogram(0,0).at(view2_num).at(tang2_num);
241-
set_tolerance(10E-3);
242-
check_if_equal(bin1, max1,"the value seen in the block at 30 degrees should be the same as the max value of the sinogram");
243-
check_if_equal(bin2, max2,"the value seen in the block at 60 degrees should be the same as the max value of the sinogram");
251+
set_tolerance(10E-2);
252+
check_if_equal(bin1, max1,"the value seen in the block at 60 degrees should be the same as the max value of the sinogram");
253+
check_if_equal(bin2, max2,"the value seen in the block at 30 degrees should be the same as the max value of the sinogram");
244254
}
245255

246256
/*! The following is a test for symmetries: a simulated image is created with spherical source in front of each detector block,

src/test/test_proj_data_info.cxx

100644100755
+43-21
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ ProjDataInfoTests::run_Blocks_DOI_test()
489489
int Bring1, Bring2, Bdet1,Bdet2, BDring1, BDring2, BDdet1, BDdet2;
490490
CartesianCoordinate3D< float> b1,b2,bd1,bd2;
491491
float doi=scannerBlocksDOI_ptr->get_average_depth_of_interaction();
492-
// timer.reset(); timer.start();
492+
timer.reset(); timer.start();
493493

494494
for (int seg =proj_data_info_blocks_doi0_ptr->get_min_segment_num(); seg <=proj_data_info_blocks_doi0_ptr->get_max_segment_num(); ++ seg)
495495
for (int ax =proj_data_info_blocks_doi0_ptr->get_min_axial_pos_num(seg); ax <=proj_data_info_blocks_doi0_ptr->get_max_axial_pos_num(seg); ++ax)
@@ -545,15 +545,30 @@ ProjDataInfoTests::run_coordinate_test()
545545
scannerBlocks_ptr->set_num_axial_crystals_per_block(1);
546546
scannerBlocks_ptr->set_axial_block_spacing(scannerBlocks_ptr->get_axial_crystal_spacing()*
547547
scannerBlocks_ptr->get_num_axial_crystals_per_block());
548-
scannerBlocks_ptr->set_transaxial_block_spacing(scannerBlocks_ptr->get_transaxial_crystal_spacing()*
549-
scannerBlocks_ptr->get_num_transaxial_crystals_per_block());
550548
scannerBlocks_ptr->set_num_transaxial_crystals_per_block(1);
551549
scannerBlocks_ptr->set_num_axial_blocks_per_bucket(1);
552550
scannerBlocks_ptr->set_num_transaxial_blocks_per_bucket(1);
551+
scannerBlocks_ptr->set_transaxial_block_spacing(scannerBlocks_ptr->get_transaxial_crystal_spacing()*
552+
scannerBlocks_ptr->get_num_transaxial_crystals_per_block());
553553
scannerBlocks_ptr->set_num_rings(1);
554554

555555
scannerBlocks_ptr->set_scanner_geometry("BlocksOnCylindrical");
556556

557+
int num_transaxial_blocks_per_bucket = scannerBlocks_ptr->get_num_transaxial_blocks_per_bucket();
558+
int num_transaxial_crystals_per_block = scannerBlocks_ptr->get_num_transaxial_crystals_per_block();
559+
int num_transaxial_buckets = scannerBlocks_ptr->get_num_transaxial_blocks()/num_transaxial_blocks_per_bucket;
560+
float transaxial_block_spacing = scannerBlocks_ptr->get_transaxial_block_spacing();
561+
float transaxial_crystal_spacing = scannerBlocks_ptr->get_transaxial_crystal_spacing();
562+
// estimate the angle covered by a bucket, alpha
563+
564+
float csi=_PI/num_transaxial_buckets;
565+
float trans_blocks_gap=transaxial_block_spacing-num_transaxial_crystals_per_block*transaxial_crystal_spacing;
566+
float csi_minus_csiGaps=csi-(csi/transaxial_block_spacing/2)*
567+
(transaxial_crystal_spacing/2+trans_blocks_gap);
568+
569+
float dx=scannerBlocks_ptr->get_effective_ring_radius()*sin(csi_minus_csiGaps);
570+
float dy=scannerBlocks_ptr->get_effective_ring_radius()-scannerBlocks_ptr->get_effective_ring_radius()*cos(csi_minus_csiGaps);
571+
557572
shared_ptr<Scanner> scannerCyl_ptr;
558573
scannerCyl_ptr.reset(new Scanner (Scanner::SAFIRDualRingPrototype));
559574
scannerCyl_ptr->set_num_axial_crystals_per_block(1);
@@ -604,7 +619,7 @@ ProjDataInfoTests::run_coordinate_test()
604619
int Bring1, Bring2, Bdet1,Bdet2, Cring1, Cring2, Cdet1, Cdet2;
605620
int RTring1, RTring2, RTdet1,RTdet2;
606621
CartesianCoordinate3D< float> b1,b2,c1,c2,roundt1, roundt2;
607-
// timer.reset(); timer.start();
622+
timer.reset(); timer.start();
608623
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorB;
609624
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorC;
610625

@@ -796,7 +811,14 @@ ProjDataInfoTests::run_coordinate_test_for_realistic_scanner()
796811

797812
int Bring1, Bring2, Bdet1,Bdet2, Cring1, Cring2, Cdet1, Cdet2;
798813
CartesianCoordinate3D< float> b1,b2,c1,c2;
799-
// timer.reset(); timer.start();
814+
815+
// estimate the angle covered by half bucket, csi
816+
float csi=_PI/scannerBlocks_ptr->get_num_transaxial_buckets();
817+
// distance between the center of the scannner and the first crystal in the bucket, r=Reffective/cos(csi)
818+
float r=scannerBlocks_ptr->get_effective_ring_radius()/cos(csi);
819+
float max_tolerance=abs(scannerBlocks_ptr->get_effective_ring_radius()-r);
820+
821+
timer.reset(); timer.start();
800822
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorB;
801823
LORInAxialAndNoArcCorrSinogramCoordinates<float> lorC;
802824

@@ -842,14 +864,15 @@ ProjDataInfoTests::run_coordinate_test_for_realistic_scanner()
842864
proj_data_info_blocks_ptr->find_cartesian_coordinates_of_detection(b1,b2,bin);
843865

844866
// we expect to be differences of the order of the mm in x and y due to the difference in geometry
845-
set_tolerance(10E-1);
846867

847-
check_if_equal(b1.z(),c1.z(), " ");
848-
check_if_equal(b2.z(),c2.z(), " ");
849-
check_if_equal(b1.y(),c1.y(), " ");
850-
check_if_equal(b2.y(),c2.y(), " ");
851-
check_if_equal(b1.x(),c1.x(), " ");
852-
check_if_equal(b2.x(),c2.x(), " ");
868+
set_tolerance(max_tolerance);
869+
870+
check_if_equal(b1.z(),c1.z(), " checking cartesian coordinate z1");
871+
check_if_equal(b2.z(),c2.z(), " checking cartesian coordinate z2");
872+
check_if_equal(b1.y(),c1.y(), " checking cartesian coordinate y1");
873+
check_if_equal(b2.y(),c2.y(), " checking cartesian coordinate y2");
874+
check_if_equal(b1.x(),c1.x(), " checking cartesian coordinate x1");
875+
check_if_equal(b2.x(),c2.x(), " checking cartesian coordinate x2");
853876

854877
}
855878
timer.stop(); std::cerr<< "-- CPU Time " << timer.value() << '\n';
@@ -948,31 +971,30 @@ run_lor_get_s_test(){
948971
// num_det_per_ring:2PI=det_id_diff:PI/2
949972
int det_id_diff=scannerBlocks_ptr->get_num_detectors_per_ring()*(_PI/2)/(2*_PI);
950973
int Ctb=scannerCyl_ptr->get_num_transaxial_crystals_per_block();
951-
float crystal_trans_spacing=scannerBlocks_ptr->get_transaxial_crystal_spacing();
974+
float transaxial_crystal_spacing=scannerBlocks_ptr->get_transaxial_crystal_spacing();
952975
float block_trans_spacing=scannerBlocks_ptr->get_transaxial_block_spacing();
953976
float prev_s=0;
954977
float prev_phi=0;
955978
for (int i=0; i<scannerCyl_ptr->get_num_transaxial_crystals_per_block();i++){
956979

957-
Cring1=0;Cdet1=i+2*Ctb-Ctb/2;
958-
Cring2=0;Cdet2=2*Ctb-Ctb/2+det_id_diff+Ctb-1 -i;
980+
Cring1=0;Cdet1=i+2*Ctb;
981+
Cring2=0;Cdet2=2*Ctb+det_id_diff+Ctb-1 -i;
959982

960983
proj_data_info_blocks_ptr->get_bin_for_det_pair(bin, Cdet1,Cring1,Cdet2,Cring1);
961984
proj_data_info_blocks_ptr->get_LOR(lorB,bin);
962985
float R=block_trans_spacing*(sin(_PI*5/12)+sin(_PI/4)+sin(_PI/12));
963986
float s=R*cos(_PI/3)+
964-
crystal_trans_spacing/2*sin(_PI/4)+
965-
(i)*crystal_trans_spacing*sin(_PI/4);
987+
transaxial_crystal_spacing/2*sin(_PI/4)+
988+
(i)*transaxial_crystal_spacing*sin(_PI/4);
966989

967-
float s_step=crystal_trans_spacing*sin(_PI/4);
990+
float s_step=transaxial_crystal_spacing*sin(_PI/4);
968991

969992
// the following fails at the moment
970993
// check_if_equal(s, lorB.s(),std::to_string(i)+ " Blocks get_s() is different");
971994
// the first value we expect to be different
995+
set_tolerance(10E-3);
972996
if (i>0){
973-
check_if_equal(s_step, lorB.s()-prev_s,std::to_string(i)+ " Blocks get_s() the step is different");//+
974-
// std::to_string(crystal_trans_spacing*sin(_PI/4)) + " lorB.s() the step is "+std::to_string(lorB.s()-prev_s)+
975-
// + "phi step is "+std::to_string(lorB.phi()-prev_phi));
997+
check_if_equal(s_step, lorB.s()-prev_s,std::to_string(i)+ " Blocks get_s() the step is different");
976998
check_if_equal(0.F, lorB.phi()-prev_phi, " Blocks get_phi() should be always the same as we are considering parallel LORs");
977999
}
9781000
prev_s=lorB.s();

0 commit comments

Comments
 (0)