122 if (
ReadStringOption(a_optionsList, option, 1,
",",
"Tolerance factor for plane index computation "))
124 Cerr(
"***** iProjectorJoseph::ReadConfigurationFile() -> Failed to correctly read the list of options !" << endl);
131 Cerr(
"***** iProjectorJoseph::ReadOptionsList() -> Tolerance factor parameter must be >2 (tolerance factor < 10^-2)" << endl);
132 Cerr(
" -> Provided parameter: "<< option[0] << endl);
149 cout <<
"This projector is a line projector that uses linear interpolation between pixels." << endl;
150 cout <<
"It is implemented from the following published paper:" << endl;
151 cout <<
"P. M. Joseph, \"An improved algorithm for reprojecting rays through pixel images\", IEEE Trans. Med. Imaging, vol. 1, pp. 192-6, 1982." << endl;
152 cout <<
"There is 1 optional parameter for this projector:" << endl;
153 cout <<
" tolerance_factor: x. -> 'x' must be an unsigned integer, and represent the tolerance precision factor for plane index computation (10^(-x))." << endl;
154 cout <<
" -> Default: 'x' = 6" << endl;
169 Cerr(
"***** iProjectorJoseph::CheckSpecificParameters() -> Tolerance factor must be defined in the specific interval : ]0 ; 1.e-2]" << endl);
170 Cerr(
"***** -> Default value is 1.e-6" << endl);
187 if (
m_verbose>=2)
Cout(
"iProjectorJoseph::InitializeSpecific() -> Use Joseph projector" << endl);
198 INTNB nElts = ( mp_nbVox[ 0 ] + 2 ) * ( mp_nbVox[ 1 ] + 2 ) * ( mp_nbVox[ 2 ] + 2 );
200 ::memset(
mp_maskPad, 0,
sizeof( uint8_t ) * nElts );
201 for(
INTNB k = 1; k < mp_nbVox[ 2 ] + 1; ++k )
203 for(
INTNB j = 1; j < mp_nbVox[ 1 ] + 1; ++j )
205 for(
INTNB i = 1; i < mp_nbVox[ 0 ] + 1; ++i )
207 mp_maskPad[ i + j * ( ( mp_nbVox[ 0 ] + 2 ) ) + k * ( mp_nbVox[ 0 ] + 2 ) * ( mp_nbVox[ 1 ] + 2 ) ] = 1;
238 max_nb_voxels_in_dimension *= 4;
240 return max_nb_voxels_in_dimension;
253 Cerr(
"***** iProjectorJoseph::ProjectWithoutTOF() -> Called while not initialized !" << endl);
258 #ifdef CASTOR_VERBOSE 261 string direction =
"";
262 if (a_direction==
FORWARD) direction =
"forward";
263 else direction =
"backward";
264 Cout(
"iProjectorJoseph::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
274 event2[ 0 ] - event1[ 0 ],
275 event2[ 1 ] - event1[ 1 ],
276 event2[ 2 ] - event1[ 2 ]
288 HPFLTNB alphaMin = 0.0, alphaMax = 1.0;
291 HPFLTNB pos[ 3 ] = { 0.0, 0.0, 0.0 };
292 HPFLTNB wfl[ 2 ] = { 0.0, 0.0 };
293 HPFLTNB wcl[ 2 ] = { 0.0, 0.0 };
294 HPFLTNB w[ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
295 int16_t index[ 2 ] = { 0, 0 };
296 int32_t finalIdx = 0;
297 int8_t limitX1 = 1; int8_t limitX2 = 1;
298 int8_t limitY1 = 1; int8_t limitY2 = 1;
299 int8_t limitZ1 = 1; int8_t limitZ2 = 1;
302 if( ::fabs( r[ 0 ] ) > ::fabs( r[ 1 ] ) )
309 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
310 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
321 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
322 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
334 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
335 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
338 if( alphaMax <= alphaMin )
return 0;
340 if( r[ 1 ] == 0.0 )
if( event1[ 1 ] < -
mp_halfFOV[ 1 ] || event1[ 1 ] >
mp_halfFOV[ 1 ] )
return 0;
341 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
344 HPFLTNB const factor( ::fabs( r[ 0 ] )
345 / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
356 int iMin = 0, iMax = 0;
362 else if( r[ 0 ] < 0.0 )
372 for(
int i = iMin; i < iMax; ++i )
376 pos[ 1 ] = event1[ 1 ] + step * ri[ 1 ];
377 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
384 finalIdx = i + ( index[ 0 ] - 1 ) *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
387 wfl[ 0 ] = pos[ 1 ] - (
m_boundY + index[ 0 ] * mp_sizeVox[ 1 ] );
388 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
389 wfl[ 0 ] /= mp_sizeVox[ 1 ];
390 wfl[ 1 ] /= mp_sizeVox[ 2 ];
393 wcl[ 0 ] = 1.0 - wfl[ 0 ];
394 wcl[ 1 ] = 1.0 - wfl[ 1 ];
397 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
398 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
399 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
400 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
403 if( index[ 0 ] <= 0 ) limitY1 = 0;
404 if( index[ 0 ] >=
mp_nbVox[ 1 ] ) limitY2 = 0;
407 if( index[ 1 ] <= 0 ) limitZ1 = 0;
408 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
412 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitY1 * limitZ1, w[ 0 ] * weight * limitY1 * limitZ1);
413 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitY1 * limitZ2, w[ 1 ] * weight * limitY1 * limitZ2);
414 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] +
m_nbVoxXY ) * limitY2 * limitZ2, w[ 2 ] * weight * limitY2 * limitZ2);
415 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] ) * limitY2 * limitZ1, w[ 3 ] * weight * limitY2 * limitZ1);
417 limitY1 = 1; limitY2 = 1;
418 limitZ1 = 1; limitZ2 = 1;
432 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
433 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
441 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
442 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
453 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
454 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
457 if( alphaMax <= alphaMin )
return 0;
459 if( r[ 0 ] == 0.0 )
if( event1[ 0 ] < -
mp_halfFOV[ 0 ] || event1[ 0 ] >
mp_halfFOV[ 0 ] )
return 0;
460 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
463 HPFLTNB const factor( ::fabs( r[ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
474 int jMin = 0, jMax = 0;
480 else if( r[ 1 ] < 0.0 )
490 for(
int j = jMin; j < jMax; ++j )
494 pos[ 0 ] = event1[ 0 ] + step * ri[ 0 ];
495 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
502 finalIdx = ( index[ 0 ] - 1 ) + j *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
505 wfl[ 0 ] = pos[ 0 ] - (
m_boundX + index[ 0 ] * mp_sizeVox[ 0 ] );
506 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
507 wfl[ 0 ] /= mp_sizeVox[ 0 ];
508 wfl[ 1 ] /= mp_sizeVox[ 2 ];
511 wcl[ 0 ] = 1.0 - wfl[ 0 ];
512 wcl[ 1 ] = 1.0 - wfl[ 1 ];
515 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
516 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
517 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
518 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
521 if( index[ 0 ] <= 0 ) limitX1 = 0;
522 if( index[ 0 ] >=
mp_nbVox[ 0 ] ) limitX2 = 0;
525 if( index[ 1 ] <= 0 ) limitZ1 = 0;
526 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
530 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitX1 * limitZ1, w[ 0 ] * weight * limitX1 * limitZ1);
531 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitX1 * limitZ2, w[ 1 ] * weight * limitX1 * limitZ2);
532 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 +
m_nbVoxXY ) * limitX2 * limitZ2, w[ 2 ] * weight * limitX2 * limitZ2);
533 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 ) * limitX2 * limitZ1, w[ 3 ] * weight * limitX2 * limitZ1);
536 limitX1 = 1; limitX2 = 1;
537 limitZ1 = 1; limitZ2 = 1;
555 Cerr(
"***** iProjectorJoseph::ProjectTOFListmode() -> Called while not initialized !" << endl);
560 #ifdef CASTOR_VERBOSE 563 string direction =
"";
564 if (a_direction==
FORWARD) direction =
"forward";
565 else direction =
"backward";
566 Cout(
"iProjectorJoseph::Project with TOF measurement -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
576 event2[ 0 ] - event1[ 0 ],
577 event2[ 1 ] - event1[ 1 ],
578 event2[ 2 ] - event1[ 2 ]
601 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
609 HPFLTNB lor_tof_center = lor_length * 0.5 + tof_delta;
612 HPFLTNB tof_edge_low[] = {0,0,0};
614 HPFLTNB tof_edge_high[] = {0,0,0};
619 for (
int ax=0;ax<3;ax++)
622 tof_center = event1[ax] + lor_tof_center * r[ax] / lor_length;
625 tof_edge_low[ax] = tof_center - tof_half_span * fabs(r[ax]) / lor_length;
628 if (tof_index>
mp_nbVox[ax]-1)
return 0;
632 tof_edge_high[ax] = tof_center + tof_half_span * fabs(r[ax]) / lor_length;
635 if (tof_index<0)
return 0;
641 HPFLTNB alphaMin = 0.0, alphaMax = 1.0;
644 HPFLTNB pos[ 3 ] = { 0.0, 0.0, 0.0 };
645 HPFLTNB wfl[ 2 ] = { 0.0, 0.0 };
646 HPFLTNB wcl[ 2 ] = { 0.0, 0.0 };
647 HPFLTNB w[ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
648 int16_t index[ 2 ] = { 0, 0 };
649 int32_t finalIdx = 0;
650 int8_t limitX1 = 1; int8_t limitX2 = 1;
651 int8_t limitY1 = 1; int8_t limitY2 = 1;
652 int8_t limitZ1 = 1; int8_t limitZ2 = 1;
655 if( ::fabs( r[ 0 ] ) > ::fabs( r[ 1 ] ) )
660 HPFLTNB const alphaX_0 = ( tof_edge_low[ 0 ] - event1[ 0 ] ) / r[ 0 ];
661 HPFLTNB const alphaX_1 = ( tof_edge_high[ 0 ] - event1[ 0 ] ) / r[ 0 ];
662 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
663 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
670 HPFLTNB const alphaY_0 = ( tof_edge_low[ 1 ] -
mp_sizeVox[ 1 ] * 0.5 - event1[ 1 ] )
672 HPFLTNB const alphaY_1 = ( tof_edge_high[ 1 ] +
mp_sizeVox[ 1 ] * 0.5 - event1[ 1 ] )
674 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
675 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
683 HPFLTNB const alphaZ_0 = ( tof_edge_low[ 2 ] -
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
685 HPFLTNB const alphaZ_1 = ( tof_edge_high[ 2 ] +
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
687 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
688 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
691 if( alphaMax <= alphaMin )
return 0;
693 if( r[ 1 ] == 0.0 )
if( event1[ 1 ] < -
mp_halfFOV[ 1 ] || event1[ 1 ] >
mp_halfFOV[ 1 ] )
return 0;
694 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
697 HPFLTNB const factor( ::fabs( r[ 0 ] ) / lor_length );
698 HPFLTNB const factor_for_tof( lor_length / r[ 0 ]) ;
709 int iMin = 0, iMax = 0;
715 else if( r[ 0 ] < 0.0 )
730 for(
int i = iMin; i < iMax; ++i )
734 pos[ 1 ] = event1[ 1 ] + step * ri[ 1 ];
735 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
742 wfl[ 0 ] = pos[ 1 ] - (
m_boundY + index[ 0 ] * mp_sizeVox[ 1 ] );
743 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
744 wfl[ 0 ] /= mp_sizeVox[ 1 ];
745 wfl[ 1 ] /= mp_sizeVox[ 2 ];
748 wcl[ 0 ] = 1.0 - wfl[ 0 ];
749 wcl[ 1 ] = 1.0 - wfl[ 1 ];
752 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
753 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
754 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
755 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
758 if( index[ 0 ] <= 0 ) limitY1 = 0;
759 if( index[ 0 ] >=
mp_nbVox[ 1 ] ) limitY2 = 0;
762 if( index[ 1 ] <= 0 ) limitZ1 = 0;
763 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
766 finalIdx = i + ( index[ 0 ] - 1 ) *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
790 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - step * factor_for_tof));
791 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
792 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - step * factor_for_tof));
793 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
800 HPFLTNB temp = ( step * factor_for_tof - lor_tof_center ) / tof_sigma;
808 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitY1 * limitZ1, w[ 0 ] * weight * tof_weight * limitY1 * limitZ1);
809 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitY1 * limitZ2, w[ 1 ] * weight * tof_weight * limitY1 * limitZ2);
810 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] +
m_nbVoxXY ) * limitY2 * limitZ2, w[ 2 ] * weight * tof_weight * limitY2 * limitZ2);
811 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
mp_nbVox[ 0 ] ) * limitY2 * limitZ1, w[ 3 ] * weight * tof_weight * limitY2 * limitZ1);
814 limitY1 = 1.0; limitY2 = 1.0;
815 limitZ1 = 1.0; limitZ2 = 1.0;
825 HPFLTNB const alphaX_0 = ( tof_edge_low[ 0 ] -
mp_sizeVox[ 0 ] * 0.5 - event1[ 0 ] )
827 HPFLTNB const alphaX_1 = ( tof_edge_high[ 0 ] +
mp_sizeVox[ 0 ] * 0.5 - event1[ 0 ] )
829 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
830 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
836 HPFLTNB const alphaY_0 = ( tof_edge_low[ 1 ] - event1[ 1 ] ) / r[ 1 ];
837 HPFLTNB const alphaY_1 = ( tof_edge_high[ 1 ] - event1[ 1 ] ) / r[ 1 ];
838 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
839 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
846 HPFLTNB const alphaZ_0 = ( tof_edge_low[ 2 ] -
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
848 HPFLTNB const alphaZ_1 = ( tof_edge_high[ 2 ] +
mp_sizeVox[ 2 ] * 0.5 - event1[ 2 ] )
850 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
851 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
854 if( alphaMax <= alphaMin )
return 0;
856 if( r[ 0 ] == 0.0 )
if( event1[ 0 ] < -
mp_halfFOV[ 0 ] || event1[ 0 ] >
mp_halfFOV[ 0 ] )
return 0;
857 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
860 HPFLTNB const factor( ::fabs( r[ 1 ] ) / lor_length );
861 HPFLTNB const factor_for_tof( lor_length / r[ 1 ] );
872 int jMin = 0, jMax = 0;
878 else if( r[ 1 ] < 0.0 )
893 for(
int j = jMin; j < jMax; ++j )
897 pos[ 0 ] = event1[ 0 ] + step * ri[ 0 ];
898 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
905 wfl[ 0 ] = pos[ 0 ] - (
m_boundX + index[ 0 ] * mp_sizeVox[ 0 ] );
906 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
907 wfl[ 0 ] /= mp_sizeVox[ 0 ];
908 wfl[ 1 ] /= mp_sizeVox[ 2 ];
911 wcl[ 0 ] = 1.0 - wfl[ 0 ];
912 wcl[ 1 ] = 1.0 - wfl[ 1 ];
915 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
916 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
917 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
918 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
921 if( index[ 0 ] <= 0 ) limitX1 = 0;
922 if( index[ 0 ] >=
mp_nbVox[ 0 ] ) limitX2 = 0;
925 if( index[ 1 ] <= 0 ) limitZ1 = 0;
926 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
929 finalIdx = ( index[ 0 ] - 1 ) + j *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
953 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - step * factor_for_tof));
954 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
955 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - step * factor_for_tof));
956 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
963 HPFLTNB temp = ( step * factor_for_tof - lor_tof_center ) / tof_sigma;
971 ap_ProjectionLine->
AddVoxel(a_direction, finalIdx * limitX1 * limitZ1, w[ 0 ] * weight * tof_weight * limitX1 * limitZ1);
972 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx +
m_nbVoxXY ) * limitX1 * limitZ2, w[ 1 ] * weight * tof_weight * limitX1 * limitZ2);
973 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 +
m_nbVoxXY ) * limitX2 * limitZ2, w[ 2 ] * weight * tof_weight * limitX2 * limitZ2);
974 ap_ProjectionLine->
AddVoxel(a_direction, ( finalIdx + 1 ) * limitX2 * limitZ1, w[ 3 ] * weight * tof_weight * limitX2 * limitZ1);
977 limitX1 = 1; limitX2 = 1;
978 limitZ1 = 1; limitZ2 = 1;
994 Cerr(
"***** iProjectorJoseph::ProjectTOFHistogram() -> Called while not initialized !" << endl);
999 #ifdef CASTOR_VERBOSE 1002 string direction =
"";
1003 if (a_direction==
FORWARD) direction =
"forward";
1004 else direction =
"backward";
1005 Cout(
"iProjectorJoseph::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
1015 event2[ 0 ] - event1[ 0 ],
1016 event2[ 1 ] - event1[ 1 ],
1017 event2[ 2 ] - event1[ 2 ]
1022 HPFLTNB lor_length_half = lor_length * 0.5;
1026 INTNB tof_half_nb_bins = tof_nb_bins/2;
1030 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
1036 HPFLTNB prev_erf = 0., new_erf = 0.;
1039 INTNB tof_bin_last = tof_half_nb_bins;
1040 INTNB tof_bin_first = -tof_half_nb_bins;
1048 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
1061 HPFLTNB alphaMin = 0.0, alphaMax = 1.0;
1064 HPFLTNB pos[ 3 ] = { 0.0, 0.0, 0.0 };
1065 HPFLTNB wfl[ 2 ] = { 0.0, 0.0 };
1066 HPFLTNB wcl[ 2 ] = { 0.0, 0.0 };
1067 HPFLTNB w[ 4 ] = { 0.0, 0.0, 0.0, 0.0 };
1068 int16_t index[ 2 ] = { 0, 0 };
1069 int32_t finalIdx = 0;
1070 int8_t limitX1 = 1; int8_t limitX2 = 1;
1071 int8_t limitY1 = 1; int8_t limitY2 = 1;
1072 int8_t limitZ1 = 1; int8_t limitZ2 = 1;
1075 if( ::fabs( r[ 0 ] ) > ::fabs( r[ 1 ] ) )
1082 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
1083 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
1094 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
1095 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
1107 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
1108 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
1111 if( alphaMax <= alphaMin )
return 0;
1113 if( r[ 1 ] == 0.0 )
if( event1[ 1 ] < -
mp_halfFOV[ 1 ] || event1[ 1 ] >
mp_halfFOV[ 1 ] )
return 0;
1114 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
1119 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1122 HPFLTNB const factor( ::fabs( r[ 0 ] ) / lor_length );
1123 HPFLTNB const factor_for_tof( lor_length / r[ 0 ] );
1134 int iMin = 0, iMax = 0;
1140 else if( r[ 0 ] < 0.0 )
1150 for(
int i = iMin; i < iMax; ++i )
1154 pos[ 1 ] = event1[ 1 ] + step * ri[ 1 ];
1155 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
1161 finalIdx = i + ( index[ 0 ] - 1 ) *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
1176 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (step * factor_for_tof - tof_half_span - lor_length_half ) /
m_TOFBinSizeInMm )));
1177 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (step * factor_for_tof + tof_half_span - lor_length_half) /
m_TOFBinSizeInMm )));
1180 lor_tof_center = lor_length_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1183 tof_bin_first_for_voxel += tof_half_nb_bins;
1184 tof_bin_last_for_voxel += tof_half_nb_bins;
1190 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - step * factor_for_tof));
1191 prev_erf = erf(temp/tof_sigma_sqrt2);
1196 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1216 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - step * factor_for_tof));
1217 new_erf = erf(temp/tof_sigma_sqrt2);
1218 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1228 HPFLTNB temp = ( step * factor_for_tof - lor_tof_center) / tof_sigma;
1240 wfl[ 0 ] = pos[ 1 ] - (
m_boundY + index[ 0 ] * mp_sizeVox[ 1 ] );
1241 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
1242 wfl[ 0 ] /= mp_sizeVox[ 1 ];
1243 wfl[ 1 ] /= mp_sizeVox[ 2 ];
1246 wcl[ 0 ] = 1.0 - wfl[ 0 ];
1247 wcl[ 1 ] = 1.0 - wfl[ 1 ];
1250 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
1251 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
1252 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
1253 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
1256 if( index[ 0 ] <= 0 ) limitY1 = 0;
1257 if( index[ 0 ] >=
mp_nbVox[ 1 ] ) limitY2 = 0;
1260 if( index[ 1 ] <= 0 ) limitZ1 = 0;
1261 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
1270 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);
1271 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);
1272 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);
1273 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);
1276 limitY1 = 1.0; limitY2 = 1.0;
1277 limitZ1 = 1.0; limitZ2 = 1.0;
1279 delete[] tof_weights_temp;
1292 alphaMin = std::max( alphaMin, std::min( alphaX_0, alphaX_1 ) );
1293 alphaMax = std::min( alphaMax, std::max( alphaX_0, alphaX_1 ) );
1301 alphaMin = std::max( alphaMin, std::min( alphaY_0, alphaY_1 ) );
1302 alphaMax = std::min( alphaMax, std::max( alphaY_0, alphaY_1 ) );
1313 alphaMin = std::max( alphaMin, std::min( alphaZ_0, alphaZ_1 ) );
1314 alphaMax = std::min( alphaMax, std::max( alphaZ_0, alphaZ_1 ) );
1317 if( alphaMax <= alphaMin )
return 0;
1319 if( r[ 0 ] == 0.0 )
if( event1[ 0 ] < -
mp_halfFOV[ 0 ] || event1[ 0 ] >
mp_halfFOV[ 0 ] )
return 0;
1320 if( r[ 2 ] == 0.0 )
if( event1[ 2 ] < -
mp_halfFOV[ 2 ] || event1[ 2 ] >
mp_halfFOV[ 2 ] )
return 0;
1324 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1327 HPFLTNB const factor( ::fabs( r[ 1 ] ) / lor_length );
1328 HPFLTNB const factor_for_tof( lor_length / r[ 1 ] );
1339 int jMin = 0, jMax = 0;
1345 else if( r[ 1 ] < 0.0 )
1355 for(
int j = jMin; j < jMax; ++j )
1359 pos[ 0 ] = event1[ 0 ] + step * ri[ 0 ];
1360 pos[ 2 ] = event1[ 2 ] + step * ri[ 2 ];
1366 finalIdx = ( index[ 0 ] - 1 ) + j *
mp_nbVox[ 0 ] + ( index[ 1 ] - 1 ) *
m_nbVoxXY;
1381 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (step * factor_for_tof - tof_half_span - lor_length_half ) /
m_TOFBinSizeInMm )));
1382 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (step * factor_for_tof + tof_half_span - lor_length_half) /
m_TOFBinSizeInMm )));
1385 lor_tof_center = lor_length_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1388 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
1391 tof_bin_first_for_voxel += tof_half_nb_bins;
1392 tof_bin_last_for_voxel += tof_half_nb_bins;
1398 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - step * factor_for_tof));
1399 prev_erf = erf(temp/tof_sigma_sqrt2);
1404 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1424 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - step * factor_for_tof));
1425 new_erf = erf(temp/tof_sigma_sqrt2);
1426 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1436 HPFLTNB temp = ( step * factor_for_tof - lor_tof_center) / tof_sigma;
1448 wfl[ 0 ] = pos[ 0 ] - (
m_boundX + index[ 0 ] * mp_sizeVox[ 0 ] );
1449 wfl[ 1 ] = pos[ 2 ] - (
m_boundZ + index[ 1 ] * mp_sizeVox[ 2 ] );
1450 wfl[ 0 ] /= mp_sizeVox[ 0 ];
1451 wfl[ 1 ] /= mp_sizeVox[ 2 ];
1454 wcl[ 0 ] = 1.0 - wfl[ 0 ];
1455 wcl[ 1 ] = 1.0 - wfl[ 1 ];
1458 w[ 0 ] = wcl[ 0 ] * wcl[ 1 ];
1459 w[ 1 ] = wcl[ 0 ] * wfl[ 1 ];
1460 w[ 2 ] = wfl[ 0 ] * wfl[ 1 ];
1461 w[ 3 ] = wfl[ 0 ] * wcl[ 1 ];
1464 if( index[ 0 ] <= 0 ) limitX1 = 0;
1465 if( index[ 0 ] >=
mp_nbVox[ 0 ] ) limitX2 = 0;
1468 if( index[ 1 ] <= 0 ) limitZ1 = 0;
1469 if( index[ 1 ] >=
mp_nbVox[ 2 ] ) limitZ2 = 0;
1480 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);
1481 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);
1482 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);
1483 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);
1485 limitX1 = 1; limitX2 = 1;
1486 limitZ1 = 1; limitZ2 = 1;
1488 delete[] tof_weights_temp;
bool m_compatibleWithSPECTAttenuationCorrection
#define SPEED_OF_LIGHT_IN_MM_PER_PS
FLTNB m_TOFGaussianNormCoef
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)
Add a voxel contribution to the line for all relevant TOF bins.
#define TWO_SQRT_TWO_LN_2
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
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.
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
bool m_TOFWeightingFcnPrecomputedFlag
bool m_TOFBinProperProcessingFlag
HPFLTNB * mp_TOFWeightingFcn
FLTNB GetLength()
This function is used to get the length of the line.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
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)
A function to project with TOF continuous information.
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)
This function is used to add a voxel contribution to the line, assuming TOF bin 0 (i...
FLTNB m_TOFResolutionInMm
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
Declaration of class iProjectorJoseph.
This class is designed to manage and store system matrix elements associated to a vEvent...
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project without TOF.
FLTNB m_TOFPrecomputedSamplingFactor
Declaration of class sOutputManager.
int ProjectTOFHistogram(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
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
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.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.
INTNB m_TOFWeightingFcnNbSamples