8 #include "iProjectorJoseph.hh" 9 #include "sOutputManager.hh" 100 if (
ReadStringOption(a_optionsList, option, 1,
",",
"Tolerance factor for plane index computation "))
102 Cerr(
"***** iProjectorJoseph::ReadConfigurationFile() -> Failed to correctly read the list of options !" << endl);
109 Cerr(
"***** iProjectorJoseph::ReadOptionsList() -> Tolerance factor parameter must be >2 (tolerance factor < 10^-2)" << endl);
110 Cerr(
" -> Provided parameter: "<< option[0] << endl);
127 cout <<
"This projector is a line projector that uses linear interpolation between pixels." << endl;
128 cout <<
"It is implemented from the following published paper:" << endl;
129 cout <<
"P. M. Joseph, \"An improved algorithm for reprojecting rays through pixel images\", IEEE Trans. Med. Imaging, vol. 1, pp. 192-6, 1982." << endl;
130 cout <<
"There is 1 optional parameter for this projector:" << endl;
131 cout <<
" tolerance_factor: x. -> 'x' must be an unsigned integer, and represent the tolerance precision factor for plane index computation (10^(-x))." << endl;
132 cout <<
" -> Default: 'x' = 6" << endl;
147 Cerr(
"***** iProjectorJoseph::CheckSpecificParameters() -> Tolerance factor must be defined in the specific interval : ]0 ; 1.e-2]" << endl);
148 Cerr(
"***** -> Default value is 1.e-6" << endl);
165 if (
m_verbose>=2)
Cout(
"iProjectorJoseph::InitializeSpecific() -> Use Joseph projector" << endl);
176 INTNB nElts = ( mp_nbVox[ 0 ] + 2 ) * ( mp_nbVox[ 1 ] + 2 ) * ( mp_nbVox[ 2 ] + 2 );
178 ::memset(
mp_maskPad, 0,
sizeof( uint8_t ) * nElts );
179 for(
INTNB k = 1; k < mp_nbVox[ 2 ] + 1; ++k )
181 for(
INTNB j = 1; j < mp_nbVox[ 1 ] + 1; ++j )
183 for(
INTNB i = 1; i < mp_nbVox[ 0 ] + 1; ++i )
185 mp_maskPad[ i + j * ( ( mp_nbVox[ 0 ] + 2 ) ) + k * ( mp_nbVox[ 0 ] + 2 ) * ( mp_nbVox[ 1 ] + 2 ) ] = 1;
216 max_nb_voxels_in_dimension *= 4;
218 return max_nb_voxels_in_dimension;
231 Cerr(
"***** iProjectorJoseph::ProjectWithoutTOF() -> Called while not initialized !" << endl);
236 #ifdef CASTOR_VERBOSE 239 string direction =
"";
240 if (a_direction==
FORWARD) direction =
"forward";
241 else direction =
"backward";
242 Cout(
"iProjectorJoseph::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
252 event2[ 0 ] - event1[ 0 ],
253 event2[ 1 ] - event1[ 1 ],
254 event2[ 2 ] - event1[ 2 ]
266 HPFLTNB alphaMin = 0.0, alphaMax = 1.0;
269 HPFLTNB pos[ 3 ] = { 0.0, 0.0, 0.0 };
270 HPFLTNB wfl[ 2 ] = { 0.0, 0.0 };
271 HPFLTNB wcl[ 2 ] = { 0.0, 0.0 };
272 HPFLTNB w[ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
273 int16_t index[ 2 ] = { 0, 0 };
274 int32_t finalIdx = 0;
275 int8_t limitX1 = 1; int8_t limitX2 = 1;
276 int8_t limitY1 = 1; int8_t limitY2 = 1;
277 int8_t limitZ1 = 1; int8_t limitZ2 = 1;
280 if( ::fabs( r[ 0 ] ) > ::fabs( r[ 1 ] ) )
287 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
288 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
299 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
300 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
312 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
313 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
316 if( alphaMax <= alphaMin )
return 0;
318 if( r[ 1 ] == 0.0 )
if( event1[ 1 ] < -
mp_halfFOV[ 1 ] || event1[ 1 ] >
mp_halfFOV[ 1 ] )
return 0;
319 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
322 HPFLTNB const factor( ::fabs( r[ 0 ] )
323 / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
334 int iMin = 0, iMax = 0;
340 else if( r[ 0 ] < 0.0 )
350 for(
int i = iMin; i < iMax; ++i )
354 pos[ 1 ] = event1[ 1 ] + step * ri[ 1 ];
355 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
362 if( index[ 0 ] <= 0 ) limitY1 = 0;
363 if( index[ 0 ] >=
mp_nbVox[ 1 ] ) limitY2 = 0;
366 if( index[ 1 ] <= 0 ) limitZ1 = 0;
367 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
370 finalIdx = i + ( index[ 0 ] - 1 ) *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
375 if ( limitY1 && limitZ1 && limitY2 && limitZ2 &&
382 wfl[ 0 ] = pos[ 1 ] - (
m_boundY + index[ 0 ] * mp_sizeVox[ 1 ] );
383 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
384 wfl[ 0 ] /= mp_sizeVox[ 1 ];
385 wfl[ 1 ] /= mp_sizeVox[ 2 ];
388 wcl[ 0 ] = 1.0 - wfl[ 0 ];
389 wcl[ 1 ] = 1.0 - wfl[ 1 ];
392 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
393 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
394 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
395 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
398 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitY1 * limitZ1, w[ 0 ] * weight * limitY1 * limitZ1);
399 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitY1 * limitZ2, w[ 1 ] * weight * limitY1 * limitZ2);
400 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] +
m_nbVoxXY ) * limitY2 * limitZ2, w[ 2 ] * weight * limitY2 * limitZ2);
401 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] ) * limitY2 * limitZ1, w[ 3 ] * weight * limitY2 * limitZ1);
403 limitY1 = 1; limitY2 = 1;
404 limitZ1 = 1; limitZ2 = 1;
418 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
419 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
427 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
428 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
439 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
440 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
443 if( alphaMax <= alphaMin )
return 0;
445 if( r[ 0 ] == 0.0 )
if( event1[ 0 ] < -
mp_halfFOV[ 0 ] || event1[ 0 ] >
mp_halfFOV[ 0 ] )
return 0;
446 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
449 HPFLTNB const factor( ::fabs( r[ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
460 int jMin = 0, jMax = 0;
466 else if( r[ 1 ] < 0.0 )
476 for(
int j = jMin; j < jMax; ++j )
480 pos[ 0 ] = event1[ 0 ] + step * ri[ 0 ];
481 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
488 finalIdx = ( index[ 0 ] - 1 ) + j *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
491 if( index[ 0 ] <= 0 ) limitX1 = 0;
492 if( index[ 0 ] >=
mp_nbVox[ 0 ] ) limitX2 = 0;
495 if( index[ 1 ] <= 0 ) limitZ1 = 0;
496 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
501 if ( limitX1 && limitZ1 && limitX2 && limitZ2 &&
508 wfl[ 0 ] = pos[ 0 ] - (
m_boundX + index[ 0 ] * mp_sizeVox[ 0 ] );
509 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
510 wfl[ 0 ] /= mp_sizeVox[ 0 ];
511 wfl[ 1 ] /= mp_sizeVox[ 2 ];
514 wcl[ 0 ] = 1.0 - wfl[ 0 ];
515 wcl[ 1 ] = 1.0 - wfl[ 1 ];
518 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
519 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
520 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
521 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
523 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitX1 * limitZ1, w[ 0 ] * weight * limitX1 * limitZ1);
524 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitX1 * limitZ2, w[ 1 ] * weight * limitX1 * limitZ2);
525 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 +
m_nbVoxXY ) * limitX2 * limitZ2, w[ 2 ] * weight * limitX2 * limitZ2);
526 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 ) * limitX2 * limitZ1, w[ 3 ] * weight * limitX2 * limitZ1);
528 limitX1 = 1; limitX2 = 1;
529 limitZ1 = 1; limitZ2 = 1;
547 Cerr(
"***** iProjectorJoseph::ProjectTOFListmode() -> Called while not initialized !" << endl);
552 #ifdef CASTOR_VERBOSE 555 string direction =
"";
556 if (a_direction==
FORWARD) direction =
"forward";
557 else direction =
"backward";
558 Cout(
"iProjectorJoseph::Project with TOF measurement -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
568 event2[ 0 ] - event1[ 0 ],
569 event2[ 1 ] - event1[ 1 ],
570 event2[ 2 ] - event1[ 2 ]
616 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
624 HPFLTNB lor_tof_center = lor_length * 0.5 + tof_delta;
627 HPFLTNB tof_edge_low[] = {0,0,0};
629 HPFLTNB tof_edge_high[] = {0,0,0};
635 for (
int ax=0;ax<3;ax++)
638 tof_center = event1[ax] + lor_tof_center * r[ax] / lor_length;
641 tof_edge_low[ax] = tof_center - tof_half_span * fabs(r[ax]) / lor_length;
644 if (tof_index>
mp_nbVox[ax]-1)
return 0;
648 tof_edge_high[ax] = tof_center + tof_half_span * fabs(r[ax]) / lor_length;
651 if (tof_index<0)
return 0;
657 HPFLTNB alphaMin = 0.0, alphaMax = 1.0;
660 HPFLTNB pos[ 3 ] = { 0.0, 0.0, 0.0 };
661 HPFLTNB wfl[ 2 ] = { 0.0, 0.0 };
662 HPFLTNB wcl[ 2 ] = { 0.0, 0.0 };
663 HPFLTNB w[ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
664 int16_t index[ 2 ] = { 0, 0 };
665 int32_t finalIdx = 0;
666 int8_t limitX1 = 1; int8_t limitX2 = 1;
667 int8_t limitY1 = 1; int8_t limitY2 = 1;
668 int8_t limitZ1 = 1; int8_t limitZ2 = 1;
671 if( ::fabs( r[ 0 ] ) > ::fabs( r[ 1 ] ) )
676 HPFLTNB const alphaX_0 = ( tof_edge_low[ 0 ] - event1[ 0 ] ) / r[ 0 ];
677 HPFLTNB const alphaX_1 = ( tof_edge_high[ 0 ] - event1[ 0 ] ) / r[ 0 ];
678 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
679 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
686 HPFLTNB const alphaY_0 = ( tof_edge_low[ 1 ] -
mp_sizeVox[ 1 ] * 0.5 - event1[ 1 ] )
688 HPFLTNB const alphaY_1 = ( tof_edge_high[ 1 ] +
mp_sizeVox[ 1 ] * 0.5 - event1[ 1 ] )
690 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
691 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
699 HPFLTNB const alphaZ_0 = ( tof_edge_low[ 2 ] -
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
701 HPFLTNB const alphaZ_1 = ( tof_edge_high[ 2 ] +
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
703 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
704 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
707 if( alphaMax <= alphaMin )
return 0;
709 if( r[ 1 ] == 0.0 )
if( event1[ 1 ] < -
mp_halfFOV[ 1 ] || event1[ 1 ] >
mp_halfFOV[ 1 ] )
return 0;
710 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
713 HPFLTNB const factor( ::fabs( r[ 0 ] ) / lor_length );
714 HPFLTNB const factor_for_tof( lor_length / r[ 0 ]) ;
725 int iMin = 0, iMax = 0;
731 else if( r[ 0 ] < 0.0 )
746 for(
int i = iMin; i < iMax; ++i )
750 pos[ 1 ] = event1[ 1 ] + step * ri[ 1 ];
751 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
758 finalIdx = i + ( index[ 0 ] - 1 ) *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
761 if( index[ 0 ] <= 0 ) limitY1 = 0;
762 if( index[ 0 ] >=
mp_nbVox[ 1 ] ) limitY2 = 0;
765 if( index[ 1 ] <= 0 ) limitZ1 = 0;
766 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
771 if ( limitY1 && limitZ1 && limitY2 && limitZ2 &&
778 wfl[ 0 ] = pos[ 1 ] - (
m_boundY + index[ 0 ] * mp_sizeVox[ 1 ] );
779 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
780 wfl[ 0 ] /= mp_sizeVox[ 1 ];
781 wfl[ 1 ] /= mp_sizeVox[ 2 ];
784 wcl[ 0 ] = 1.0 - wfl[ 0 ];
785 wcl[ 1 ] = 1.0 - wfl[ 1 ];
788 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
789 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
790 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
791 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
820 HPFLTNB sum_tof_gaussian_norm_coef = 0.;
827 Cerr(
"***** iProjectorJoseph::ProjectTOFListmode()() -> TOF proper processing not implemented for joseph. Check code !" << endl);
834 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
837 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
850 tof_weight /= sum_tof_gaussian_norm_coef;
853 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitY1 * limitZ1, w[ 0 ] * weight * tof_weight * limitY1 * limitZ1);
854 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitY1 * limitZ2, w[ 1 ] * weight * tof_weight * limitY1 * limitZ2);
855 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] +
m_nbVoxXY ) * limitY2 * limitZ2, w[ 2 ] * weight * tof_weight * limitY2 * limitZ2);
856 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] ) * limitY2 * limitZ1, w[ 3 ] * weight * tof_weight * limitY2 * limitZ1);
858 limitY1 = 1.0; limitY2 = 1.0;
859 limitZ1 = 1.0; limitZ2 = 1.0;
869 HPFLTNB const alphaX_0 = ( tof_edge_low[ 0 ] -
mp_sizeVox[ 0 ] * 0.5 - event1[ 0 ] )
871 HPFLTNB const alphaX_1 = ( tof_edge_high[ 0 ] +
mp_sizeVox[ 0 ] * 0.5 - event1[ 0 ] )
873 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
874 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
880 HPFLTNB const alphaY_0 = ( tof_edge_low[ 1 ] - event1[ 1 ] ) / r[ 1 ];
881 HPFLTNB const alphaY_1 = ( tof_edge_high[ 1 ] - event1[ 1 ] ) / r[ 1 ];
882 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
883 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
890 HPFLTNB const alphaZ_0 = ( tof_edge_low[ 2 ] -
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
892 HPFLTNB const alphaZ_1 = ( tof_edge_high[ 2 ] +
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
894 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
895 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
898 if( alphaMax <= alphaMin )
return 0;
900 if( r[ 0 ] == 0.0 )
if( event1[ 0 ] < -
mp_halfFOV[ 0 ] || event1[ 0 ] >
mp_halfFOV[ 0 ] )
return 0;
901 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
904 HPFLTNB const factor( ::fabs( r[ 1 ] ) / lor_length );
905 HPFLTNB const factor_for_tof( lor_length / r[ 1 ] );
916 int jMin = 0, jMax = 0;
922 else if( r[ 1 ] < 0.0 )
937 for(
int j = jMin; j < jMax; ++j )
941 pos[ 0 ] = event1[ 0 ] + step * ri[ 0 ];
942 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
949 finalIdx = ( index[ 0 ] - 1 ) + j *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
952 if( index[ 0 ] <= 0 ) limitX1 = 0;
953 if( index[ 0 ] >=
mp_nbVox[ 0 ] ) limitX2 = 0;
956 if( index[ 1 ] <= 0 ) limitZ1 = 0;
957 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
962 if ( limitX1 && limitZ1 && limitX2 && limitZ2 &&
969 wfl[ 0 ] = pos[ 0 ] - (
m_boundX + index[ 0 ] * mp_sizeVox[ 0 ] );
970 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
971 wfl[ 0 ] /= mp_sizeVox[ 0 ];
972 wfl[ 1 ] /= mp_sizeVox[ 2 ];
975 wcl[ 0 ] = 1.0 - wfl[ 0 ];
976 wcl[ 1 ] = 1.0 - wfl[ 1 ];
979 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
980 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
981 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
982 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
1010 HPFLTNB sum_tof_gaussian_norm_coef = 0.;
1017 Cerr(
"***** iProjectorJoseph::ProjectTOFListmode()() -> TOF proper processing not implemented for joseph. Check code !" << endl);
1024 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
1027 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
1040 tof_weight /= sum_tof_gaussian_norm_coef;
1043 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitX1 * limitZ1, w[ 0 ] * weight * tof_weight * limitX1 * limitZ1);
1044 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitX1 * limitZ2, w[ 1 ] * weight * tof_weight * limitX1 * limitZ2);
1045 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 +
m_nbVoxXY ) * limitX2 * limitZ2, w[ 2 ] * weight * tof_weight * limitX2 * limitZ2);
1046 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 ) * limitX2 * limitZ1, w[ 3 ] * weight * tof_weight * limitX2 * limitZ1);
1048 limitX1 = 1; limitX2 = 1;
1049 limitZ1 = 1; limitZ2 = 1;
1070 Cerr(
"***** iProjectorJoseph::ProjectTOFHistogram() -> Called while not initialized !" << endl);
1075 #ifdef CASTOR_VERBOSE 1078 string direction =
"";
1079 if (a_direction==
FORWARD) direction =
"forward";
1080 else direction =
"backward";
1081 Cout(
"iProjectorJoseph::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
1091 event2[ 0 ] - event1[ 0 ],
1092 event2[ 1 ] - event1[ 1 ],
1093 event2[ 2 ] - event1[ 2 ]
1098 HPFLTNB lor_length_half = lor_length * 0.5;
1102 INTNB tof_half_nb_bins = tof_nb_bins/2;
1106 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
1112 HPFLTNB prev_erf = 0., new_erf = 0.;
1115 INTNB tof_bin_last = tof_half_nb_bins;
1116 INTNB tof_bin_first = -tof_half_nb_bins;
1124 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
1137 HPFLTNB alphaMin = 0.0, alphaMax = 1.0;
1140 HPFLTNB pos[ 3 ] = { 0.0, 0.0, 0.0 };
1141 HPFLTNB wfl[ 2 ] = { 0.0, 0.0 };
1142 HPFLTNB wcl[ 2 ] = { 0.0, 0.0 };
1143 HPFLTNB w[ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
1144 int16_t index[ 2 ] = { 0, 0 };
1145 int32_t finalIdx = 0;
1146 int8_t limitX1 = 1; int8_t limitX2 = 1;
1147 int8_t limitY1 = 1; int8_t limitY2 = 1;
1148 int8_t limitZ1 = 1; int8_t limitZ2 = 1;
1151 if( ::fabs( r[ 0 ] ) > ::fabs( r[ 1 ] ) )
1158 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
1159 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
1170 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
1171 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
1183 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
1184 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
1187 if( alphaMax <= alphaMin )
return 0;
1189 if( r[ 1 ] == 0.0 )
if( event1[ 1 ] < -
mp_halfFOV[ 1 ] || event1[ 1 ] >
mp_halfFOV[ 1 ] )
return 0;
1190 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
1195 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1198 HPFLTNB const factor( ::fabs( r[ 0 ] ) / lor_length );
1199 HPFLTNB const factor_for_tof( lor_length / r[ 0 ] );
1210 int iMin = 0, iMax = 0;
1216 else if( r[ 0 ] < 0.0 )
1226 for(
int i = iMin; i < iMax; ++i )
1230 pos[ 1 ] = event1[ 1 ] + step * ri[ 1 ];
1231 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
1237 finalIdx = i + ( index[ 0 ] - 1 ) *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
1240 if( index[ 0 ] <= 0 ) limitY1 = 0;
1241 if( index[ 0 ] >=
mp_nbVox[ 1 ] ) limitY2 = 0;
1244 if( index[ 1 ] <= 0 ) limitZ1 = 0;
1245 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
1250 if ( limitY1 && limitZ1 && limitY2 && limitZ2 &&
1266 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (step * factor_for_tof - tof_half_span - lor_length_half ) /
m_TOFBinSizeInMm )));
1267 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (step * factor_for_tof + tof_half_span - lor_length_half) /
m_TOFBinSizeInMm )));
1270 lor_tof_center = lor_length_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1273 tof_bin_first_for_voxel += tof_half_nb_bins;
1274 tof_bin_last_for_voxel += tof_half_nb_bins;
1280 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - step * factor_for_tof));
1281 prev_erf = erf(temp/tof_sigma_sqrt2);
1286 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1306 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - step * factor_for_tof));
1307 new_erf = erf(temp/tof_sigma_sqrt2);
1308 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1318 HPFLTNB temp = ( step * factor_for_tof - lor_tof_center) / tof_sigma;
1330 wfl[ 0 ] = pos[ 1 ] - (
m_boundY + index[ 0 ] * mp_sizeVox[ 1 ] );
1331 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
1332 wfl[ 0 ] /= mp_sizeVox[ 1 ];
1333 wfl[ 1 ] /= mp_sizeVox[ 2 ];
1336 wcl[ 0 ] = 1.0 - wfl[ 0 ];
1337 wcl[ 1 ] = 1.0 - wfl[ 1 ];
1340 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
1341 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
1342 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
1343 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
1352 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, finalIdx * limitY1 * limitZ1, w[ 0 ] * weight * limitY1 * limitZ1, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1353 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, ( finalIdx +
m_nbVoxXY ) * limitY1 * limitZ2, w[ 1 ] * weight * limitY1 * limitZ2 , tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1354 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, ( finalIdx +
mp_nbVox[ 0 ] +
m_nbVoxXY ) * limitY2 * limitZ2, w[ 2 ] * weight * limitY2 * limitZ2 , tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1355 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, ( finalIdx +
mp_nbVox[ 0 ] ) * limitY2 * limitZ1, w[ 3 ] * weight * limitY2 * limitZ1 , tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1358 limitY1 = 1.0; limitY2 = 1.0;
1359 limitZ1 = 1.0; limitZ2 = 1.0;
1361 delete[] tof_weights_temp;
1374 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
1375 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
1383 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
1384 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
1395 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
1396 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
1399 if( alphaMax <= alphaMin )
return 0;
1401 if( r[ 0 ] == 0.0 )
if( event1[ 0 ] < -
mp_halfFOV[ 0 ] || event1[ 0 ] >
mp_halfFOV[ 0 ] )
return 0;
1402 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
1406 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1409 HPFLTNB const factor( ::fabs( r[ 1 ] ) / lor_length );
1410 HPFLTNB const factor_for_tof( lor_length / r[ 1 ] );
1421 int jMin = 0, jMax = 0;
1427 else if( r[ 1 ] < 0.0 )
1437 for(
int j = jMin; j < jMax; ++j )
1441 pos[ 0 ] = event1[ 0 ] + step * ri[ 0 ];
1442 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
1448 finalIdx = ( index[ 0 ] - 1 ) + j *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
1451 if( index[ 0 ] <= 0 ) limitX1 = 0;
1452 if( index[ 0 ] >=
mp_nbVox[ 0 ] ) limitX2 = 0;
1455 if( index[ 1 ] <= 0 ) limitZ1 = 0;
1456 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
1461 if ( limitX1 && limitZ1 && limitX2 && limitZ2 &&
1477 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (step * factor_for_tof - tof_half_span - lor_length_half ) /
m_TOFBinSizeInMm )));
1478 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (step * factor_for_tof + tof_half_span - lor_length_half) /
m_TOFBinSizeInMm )));
1481 lor_tof_center = lor_length_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1484 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
1487 tof_bin_first_for_voxel += tof_half_nb_bins;
1488 tof_bin_last_for_voxel += tof_half_nb_bins;
1494 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - step * factor_for_tof));
1495 prev_erf = erf(temp/tof_sigma_sqrt2);
1500 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1520 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - step * factor_for_tof));
1521 new_erf = erf(temp/tof_sigma_sqrt2);
1522 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1532 HPFLTNB temp = ( step * factor_for_tof - lor_tof_center) / tof_sigma;
1544 wfl[ 0 ] = pos[ 0 ] - (
m_boundX + index[ 0 ] * mp_sizeVox[ 0 ] );
1545 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
1546 wfl[ 0 ] /= mp_sizeVox[ 0 ];
1547 wfl[ 1 ] /= mp_sizeVox[ 2 ];
1550 wcl[ 0 ] = 1.0 - wfl[ 0 ];
1551 wcl[ 1 ] = 1.0 - wfl[ 1 ];
1554 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
1555 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
1556 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
1557 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
1568 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, finalIdx * limitX1 * limitZ1, w[ 0 ] * weight * limitX1 * limitZ1, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1569 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, ( finalIdx +
m_nbVoxXY ) * limitX1 * limitZ2, w[ 1 ] * weight * limitX1 * limitZ2, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1570 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, ( finalIdx + 1 +
m_nbVoxXY ) * limitX2 * limitZ2, w[ 2 ] * weight * limitX2 * limitZ2, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1571 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, ( finalIdx + 1 ) * limitX2 * limitZ1, w[ 3 ] * weight * limitX2 * limitZ1, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1573 limitX1 = 1; limitX2 = 1;
1574 limitZ1 = 1; limitZ2 = 1;
1576 delete[] tof_weights_temp;
FLTNB m_TOFLargestResolutionInMm
bool m_compatibleWithSPECTAttenuationCorrection
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the 'a_input' string corresponding to the 'a_option' into 'a_nbElts' elements, using the 'sep' separator. The results are returned in the templated 'ap_return' dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
void ShowHelpSpecific()
A function used to show help about the child module.
void AddVoxelAllTOFBins(int a_direction, INTNB a_voxelIndex, FLTNB a_voxelWeight, HPFLTNB *a_tofWeights, INTNB a_tofBinFirst, INTNB a_tofBinLast)
FLTNB GetTOFMeasurementInPs()
This function is used to get the TOF measurement in ps.
This class is designed to generically described any on-the-fly projector.
#define SPEED_OF_LIGHT_IN_MM_PER_PS
int ReadConfigurationFile(const string &a_configurationFile)
bool m_TOFWeightingFcnPrecomputedFlag
bool m_TOFBinProperProcessingFlag
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
FLTNB GetLength()
This function is used to get the length of the line.
int ReadOptionsList(const string &a_optionsList)
HPFLTNB ** m2p_TOFWeightingFcn
FLTNB * mp_TOFProbabilities
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
~iProjectorJoseph()
The destructor of iProjectorJoseph.
int ProjectTOFListmode(int a_direction, oProjectionLine *ap_ProjectionLine)
FLTNB * GetPosition1()
This function is used to get the pointer to the mp_position1 (3-values tab).
void AddVoxel(int a_direction, INTNB a_voxelIndice, FLTNB a_voxelWeight)
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
FLTNB * mp_TOFResolutionInMm
FLTNB * mp_TOFGaussianNormCoef
This class is designed to manage and store system matrix elements associated to a vEvent...
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
FLTNB m_TOFPrecomputedSamplingFactor
int GetNbTOFResolutions()
int ProjectTOFHistogram(int a_direction, oProjectionLine *ap_ProjectionLine)
int GetNbTOFBins()
This function is used to get the number of TOF bins in use.
FLTNB * GetPosition2()
This function is used to get the pointer to the mp_position2 (3-values tab).
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
iProjectorJoseph()
The constructor of iProjectorJoseph.
bool m_compatibleWithCompression
#define TWO_SQRT_TWO_LN_2
bool IsVoxelMasked(INTNB a_voxIndex)
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.
INTNB m_TOFWeightingFcnNbSamples