95 cout <<
"This projector is a simple line projector that computes the exact path length of a line through the voxels." << endl;
96 cout <<
"It is basically an incremental version of the original algorithm proposed by R. L. Siddon (see the classicSiddon projector)." << endl;
97 cout <<
"It is implemented from the following published paper:" << endl;
98 cout <<
"F. Jacobs et al, \"A fast algorithm to calculate the exact radiological path through a pixel or voxel space\", J. Comput. Inf. Technol., vol. 6, pp. 89-94, 1998." << endl;
122 if (
m_verbose>=2)
Cout(
"iProjectorIncrementalSiddon::InitializeSpecific() -> Use incremental Siddon projector" << endl);
140 max_nb_voxels_in_dimension *= 4;
142 return max_nb_voxels_in_dimension;
155 Cerr(
"***** iProjectorIncrementalSiddon::ProjectWithoutTOF() -> Called while not initialized !" << endl);
160 #ifdef CASTOR_VERBOSE
163 string direction =
"";
164 if (a_direction==
FORWARD) direction =
"forward";
165 else direction =
"backward";
166 Cout(
"iProjectorIncrementalSiddon::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
173 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
174 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
184 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
185 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
187 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
189 event2[ 0 ] - event1[ 0 ],
190 event2[ 1 ] - event1[ 1 ],
191 event2[ 2 ] - event1[ 2 ]
195 for(
int i = 0; i < 3; ++i )
197 if( delta_pos[ i ] != 0.0 )
199 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
200 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
201 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
202 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
208 if( alphaMax <= alphaMin )
return 0;
212 int iMin = 0, iMax = 0;
213 int jMin = 0, jMax = 0;
214 int kMin = 0, kMax = 0;
217 if( delta_pos[ 0 ] > 0.0f )
220 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
222 else if( delta_pos[ 0 ] < 0.0f )
225 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
227 if( delta_pos[ 0 ] == 0 )
233 if( delta_pos[ 1 ] > 0 )
236 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
238 else if( delta_pos[ 1 ] < 0 )
241 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
243 else if( delta_pos[ 1 ] == 0 )
249 if( delta_pos[ 2 ] > 0 )
252 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
254 else if( delta_pos[ 2 ] < 0 )
257 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
259 else if( delta_pos[ 2 ] == 0 )
265 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
266 + ( kMax - kMin + 1 );
269 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
272 if( delta_pos[ 0 ] > 0 )
273 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
274 else if( delta_pos[ 0 ] < 0 )
275 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
278 if( delta_pos[ 1 ] > 0 )
279 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
280 else if( delta_pos[ 1 ] < 0 )
281 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
284 if( delta_pos[ 2 ] > 0 )
285 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
286 else if( delta_pos[ 2 ] < 0 )
287 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
297 INTNB index_u[ 3 ] = {
298 (delta_pos[ 0 ] < 0) ? -1 : 1,
299 (delta_pos[ 1 ] < 0) ? -1 : 1,
300 (delta_pos[ 2 ] < 0) ? -1 : 1
304 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
305 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
306 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
309 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
310 (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
313 HPFLTNB const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
314 INTNB index_ijk[ 3 ] = {
328 for(
int nP = 0; nP < n - 1; ++nP )
330 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
331 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
334 if( ( alpha_XYZ[ 0 ] >= alphaMin )
335 && ( index_ijk[ 0 ] - 1 >= 0 )
336 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
337 && ( index_ijk[ 1 ] - 1 >= 0 )
338 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
339 && ( index_ijk[ 2 ] - 1 >= 0 )
340 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
342 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
343 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
348 alpha_c = alpha_XYZ[ 0 ];
349 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
350 index_ijk[ 0 ] += index_u[ 0 ];
352 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
353 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
356 if( ( alpha_XYZ[ 1 ] >= alphaMin )
357 && ( index_ijk[ 0 ] - 1 >= 0 )
358 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
359 && ( index_ijk[ 1 ] - 1 >= 0 )
360 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
361 && ( index_ijk[ 2 ] - 1 >= 0 )
362 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
364 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
365 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
370 alpha_c = alpha_XYZ[ 1 ];
371 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
372 index_ijk[ 1 ] += index_u[ 1 ];
374 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
375 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
378 if( ( alpha_XYZ[ 2 ] >= alphaMin )
379 && ( index_ijk[ 0 ] - 1 >= 0 )
380 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
381 && ( index_ijk[ 1 ] - 1 >= 0 )
382 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
383 && ( index_ijk[ 2 ] - 1 >= 0 )
384 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
386 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
387 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
392 alpha_c = alpha_XYZ[ 2 ];
393 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
394 index_ijk[ 2 ] += index_u[ 2 ];
411 Cerr(
"***** iProjectorIncrementalSiddon::ProjectWithTOFPos() -> Called while not initialized !" << endl);
416 #ifdef CASTOR_VERBOSE
419 string direction =
"";
420 if (a_direction==
FORWARD) direction =
"forward";
421 else direction =
"backward";
422 Cout(
"iProjectorIncrementalSiddon::Project with TOF position -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
429 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
430 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
440 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
441 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
443 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
445 event2[ 0 ] - event1[ 0 ],
446 event2[ 1 ] - event1[ 1 ],
447 event2[ 2 ] - event1[ 2 ]
456 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
463 HPFLTNB lor_tof_center = length_LOR * 0.5 + tof_delta;
466 HPFLTNB tof_edge_low[] = {0,0,0};
468 HPFLTNB tof_edge_high[] = {0,0,0};
470 INTNB tof_index_low[] = {0,0,0};
471 INTNB tof_index_high[] = {0,0,0};
474 for (
int ax=0;ax<3;ax++)
477 tof_center = event1[ax] + lor_tof_center * delta_pos[ax] / length_LOR;
480 tof_edge_low[ax] = tof_center - tof_half_span * fabs(delta_pos[ax]) / length_LOR;
483 if (tof_index_low[ax]>
mp_nbVox[ax]-1)
return 0;
487 tof_edge_high[ax] = tof_center + tof_half_span * fabs(delta_pos[ax]) / length_LOR;
490 if (tof_index_high[ax]<0)
return 0;
495 for(
int i = 0; i < 3; ++i )
497 if( delta_pos[ i ] != 0.0 )
499 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
500 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
501 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
502 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
508 if( alphaMax <= alphaMin )
return 0;
512 int iMin = 0, iMax = 0;
513 int jMin = 0, jMax = 0;
514 int kMin = 0, kMax = 0;
517 if( delta_pos[ 0 ] > 0.0f )
520 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
522 else if( delta_pos[ 0 ] < 0.0f )
525 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
527 if( delta_pos[ 0 ] == 0 )
533 if( delta_pos[ 1 ] > 0 )
536 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
538 else if( delta_pos[ 1 ] < 0 )
541 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
543 else if( delta_pos[ 1 ] == 0 )
549 if( delta_pos[ 2 ] > 0 )
552 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
554 else if( delta_pos[ 2 ] < 0 )
557 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
559 else if( delta_pos[ 2 ] == 0 )
565 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
566 + ( kMax - kMin + 1 );
569 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
572 if( delta_pos[ 0 ] > 0 )
573 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
574 else if( delta_pos[ 0 ] < 0 )
575 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
578 if( delta_pos[ 1 ] > 0 )
579 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
580 else if( delta_pos[ 1 ] < 0 )
581 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
584 if( delta_pos[ 2 ] > 0 )
585 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
586 else if( delta_pos[ 2 ] < 0 )
587 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
597 INTNB index_u[ 3 ] = {
598 (delta_pos[ 0 ] < 0) ? -1 : 1,
599 (delta_pos[ 1 ] < 0) ? -1 : 1,
600 (delta_pos[ 2 ] < 0) ? -1 : 1
604 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
605 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
606 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
609 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ], (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
612 HPFLTNB const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
613 INTNB index_ijk[ 3 ] = {
623 HPFLTNB previous_edge_erf = 0.;
625 bool previous_edge_erf_initialized =
false;
631 for(
int nP = 0; nP < n - 1; ++nP )
633 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
634 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
637 if( ( alpha_XYZ[ 0 ] >= alphaMin )
638 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
639 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
640 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
641 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
642 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
643 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
646 if (!previous_edge_erf_initialized)
648 previous_edge_erf = erf( (length_LOR *alpha_c - lor_tof_center) / tof_sigma_sqrt2 );
649 previous_edge_erf_initialized =
true;
652 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
655 next_edge_erf = erf( (length_LOR * alpha_XYZ[ 0 ] - lor_tof_center) / tof_sigma_sqrt2 );
657 coeff = 0.5 * std::fabs(previous_edge_erf - next_edge_erf) ;
659 previous_edge_erf = next_edge_erf;
665 alpha_c = alpha_XYZ[ 0 ];
666 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
667 index_ijk[ 0 ] += index_u[ 0 ];
669 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
670 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
673 if( ( alpha_XYZ[ 1 ] >= alphaMin )
674 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
675 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
676 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
677 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
678 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
679 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
682 if (!previous_edge_erf_initialized)
684 previous_edge_erf = erf( (length_LOR *alpha_c - lor_tof_center) / tof_sigma_sqrt2 );
685 previous_edge_erf_initialized =
true;
688 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
691 next_edge_erf = erf( (length_LOR * alpha_XYZ[ 1 ] - lor_tof_center) / tof_sigma_sqrt2 );
693 coeff = 0.5 * std::fabs(previous_edge_erf - next_edge_erf) ;
695 previous_edge_erf = next_edge_erf;
702 alpha_c = alpha_XYZ[ 1 ];
703 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
704 index_ijk[ 1 ] += index_u[ 1 ];
706 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
707 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
710 if( ( alpha_XYZ[ 2 ] >= alphaMin )
711 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
712 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
713 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
714 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
715 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
716 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
719 if (!previous_edge_erf_initialized)
721 previous_edge_erf = erf( (length_LOR *alpha_c - lor_tof_center) / tof_sigma_sqrt2 );
722 previous_edge_erf_initialized =
true;
725 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
728 next_edge_erf = erf( (length_LOR * alpha_XYZ[ 2 ] - lor_tof_center) / tof_sigma_sqrt2 );
730 coeff = 0.5 * std::fabs(previous_edge_erf - next_edge_erf) ;
732 previous_edge_erf = next_edge_erf;
739 alpha_c = alpha_XYZ[ 2 ];
740 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
741 index_ijk[ 2 ] += index_u[ 2 ];
758 Cerr(
"***** iProjectorIncrementalSiddon::ProjectWithTOFBin() -> Called while not initialized !" << endl);
763 #ifdef CASTOR_VERBOSE
766 string direction =
"";
767 if (a_direction==
FORWARD) direction =
"forward";
768 else direction =
"backward";
769 Cout(
"iProjectorIncrementalSiddon::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
776 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
777 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
783 HPFLTNB length_LOR_half = length_LOR * 0.5;
788 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
789 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
791 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
793 event2[ 0 ] - event1[ 0 ],
794 event2[ 1 ] - event1[ 1 ],
795 event2[ 2 ] - event1[ 2 ]
804 INTNB tof_half_nb_bins = tof_nb_bins/2;
818 INTNB tof_bin_last = tof_half_nb_bins;
819 INTNB tof_bin_first = -tof_half_nb_bins;
833 for(
int i = 0; i < 3; ++i )
835 if( delta_pos[ i ] != 0.0 )
837 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
838 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
839 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
840 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
846 if( alphaMax <= alphaMin )
return 0;
851 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
855 int iMin = 0, iMax = 0;
856 int jMin = 0, jMax = 0;
857 int kMin = 0, kMax = 0;
860 if( delta_pos[ 0 ] > 0.0f )
863 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
865 else if( delta_pos[ 0 ] < 0.0f )
868 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
870 if( delta_pos[ 0 ] == 0 )
876 if( delta_pos[ 1 ] > 0 )
879 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
881 else if( delta_pos[ 1 ] < 0 )
884 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
886 else if( delta_pos[ 1 ] == 0 )
892 if( delta_pos[ 2 ] > 0 )
895 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
897 else if( delta_pos[ 2 ] < 0 )
900 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
902 else if( delta_pos[ 2 ] == 0 )
908 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
909 + ( kMax - kMin + 1 );
912 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
915 if( delta_pos[ 0 ] > 0 )
916 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
917 else if( delta_pos[ 0 ] < 0 )
918 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
921 if( delta_pos[ 1 ] > 0 )
922 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
923 else if( delta_pos[ 1 ] < 0 )
924 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
927 if( delta_pos[ 2 ] > 0 )
928 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
929 else if( delta_pos[ 2 ] < 0 )
930 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
940 INTNB index_u[ 3 ] = {
941 (delta_pos[ 0 ] < 0) ? -1 : 1,
942 (delta_pos[ 1 ] < 0) ? -1 : 1,
943 (delta_pos[ 2 ] < 0) ? -1 : 1
947 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
948 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
949 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
952 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ], (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
955 HPFLTNB const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
956 INTNB index_ijk[ 3 ] = {
969 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
970 for(
int nP = 0; nP < n - 1; ++nP )
972 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
973 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
976 if( ( alpha_XYZ[ 0 ] >= alphaMin )
977 && ( index_ijk[ 0 ] - 1 >= 0 )
978 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
979 && ( index_ijk[ 1 ] - 1 >= 0 )
980 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
981 && ( index_ijk[ 2 ] - 1 >= 0 )
982 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
984 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
989 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
992 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(trunc( (alpha_c * length_LOR - tof_half_span - length_LOR_half ) / tof_bin_size )));
993 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(trunc( (alpha_XYZ[ 0 ] * length_LOR + tof_half_span - length_LOR_half) / tof_bin_size )));
994 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel * tof_bin_size;
997 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
1000 tof_bin_first_for_voxel += tof_half_nb_bins;
1001 tof_bin_last_for_voxel += tof_half_nb_bins;
1005 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1013 HPFLTNB temp = (( alpha_XYZ[ 0 ] + alpha_c ) * 0.5 * length_LOR - lor_tof_center) / tof_sigma;
1014 tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef * coeff;
1016 tof_norm_coef += tof_weight;
1018 tof_weights_temp[tof_bin] = tof_weight;
1020 lor_tof_center += tof_bin_size;
1024 if (tof_norm_coef>0.)
1027 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1029 tof_weights_temp[tof_bin] /= tof_norm_coef;
1032 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1037 alpha_c = alpha_XYZ[ 0 ];
1038 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
1039 index_ijk[ 0 ] += index_u[ 0 ];
1041 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
1042 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
1045 if( ( alpha_XYZ[ 1 ] >= alphaMin )
1046 && ( index_ijk[ 0 ] - 1 >= 0 )
1047 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1048 && ( index_ijk[ 1 ] - 1 >= 0 )
1049 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1050 && ( index_ijk[ 2 ] - 1 >= 0 )
1051 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1053 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1058 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
1061 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(trunc( (alpha_c * length_LOR - tof_half_span - length_LOR_half ) / tof_bin_size )));
1062 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(trunc( (alpha_XYZ[ 1 ] * length_LOR + tof_half_span - length_LOR_half) / tof_bin_size )));
1063 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel * tof_bin_size;
1066 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
1069 tof_bin_first_for_voxel += tof_half_nb_bins;
1070 tof_bin_last_for_voxel += tof_half_nb_bins;
1074 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1082 HPFLTNB temp = (( alpha_XYZ[ 1 ] + alpha_c ) * 0.5 * length_LOR - lor_tof_center) / tof_sigma;
1083 tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef * coeff;
1085 tof_norm_coef += tof_weight;
1087 tof_weights_temp[tof_bin] = tof_weight;
1089 lor_tof_center += tof_bin_size;
1093 if (tof_norm_coef>0.)
1096 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1098 tof_weights_temp[tof_bin] /= tof_norm_coef;
1101 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1107 alpha_c = alpha_XYZ[ 1 ];
1108 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
1109 index_ijk[ 1 ] += index_u[ 1 ];
1111 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
1112 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
1115 if( ( alpha_XYZ[ 2 ] >= alphaMin )
1116 && ( index_ijk[ 0 ] - 1 >= 0 )
1117 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1118 && ( index_ijk[ 1 ] - 1 >= 0 )
1119 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1120 && ( index_ijk[ 2 ] - 1 >= 0 )
1121 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1123 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1128 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
1131 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(trunc( (alpha_c * length_LOR - tof_half_span - length_LOR_half ) / tof_bin_size )));
1132 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(trunc( (alpha_XYZ[ 2 ] * length_LOR + tof_half_span - length_LOR_half) / tof_bin_size )));
1133 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel * tof_bin_size;
1136 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
1139 tof_bin_first_for_voxel += tof_half_nb_bins;
1140 tof_bin_last_for_voxel += tof_half_nb_bins;
1144 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1152 HPFLTNB temp = (( alpha_XYZ[ 2 ] + alpha_c ) * 0.5 * length_LOR - lor_tof_center) / tof_sigma;
1153 tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef * coeff;
1155 tof_norm_coef += tof_weight;
1157 tof_weights_temp[tof_bin] = tof_weight;
1159 lor_tof_center += tof_bin_size;
1163 if (tof_norm_coef>0.)
1166 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1168 tof_weights_temp[tof_bin] /= tof_norm_coef;
1171 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1177 alpha_c = alpha_XYZ[ 2 ];
1178 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
1179 index_ijk[ 2 ] += index_u[ 2 ];
1183 delete[] tof_weights_temp;
bool m_compatibleWithSPECTAttenuationCorrection
~iProjectorIncrementalSiddon()
The destructor of iProjectorIncrementalSiddon.
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
void ShowHelpSpecific()
A function used to show help about the child module.
This class is designed to generically described any on-the-fly projector.
FLTNB GetTOFMeasurement()
This function is used to get the TOF measurement.
Declaration of class iProjectorIncrementalSiddon.
FLTNB GetLength()
This function is used to get the length of the line.
FLTNB GetTOFResolution()
This function is used to get the TOF resolution.
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...
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
int ProjectWithTOFPos(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
iProjectorIncrementalSiddon()
The constructor of iProjectorIncrementalSiddon.
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
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.
Declaration of class sOutputManager.
int ProjectWithTOFBin(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).
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
FLTNB GetTOFBinSize()
This function is used to get the size in ps of a TOF bin.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
bool m_compatibleWithCompression
void AddVoxelInTOFBin(int a_direction, int a_TOFBin, INTNB a_voxelIndice, FLTNB a_voxelWeight)
This function is used to add a voxel contribution to the line and provided TOF bin.
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.