97 if (
ReadStringOption(a_optionsList, option, 1,
",",
"Tolerance factor for plane index computation "))
99 Cerr(
"***** iProjectorJoseph::ReadConfigurationFile() -> Failed to correctly read the list of options !" << endl);
106 Cerr(
"***** iProjectorJoseph::ReadOptionsList() -> Tolerance factor parameter must be >2 (tolerance factor < 10^-2)" << endl);
107 Cerr(
" -> Provided parameter: "<< option[0] << endl);
124 cout <<
"This projector is a line projector based on computations of overlap between a pair of detection elements and voxels." << endl;
125 cout <<
"It is implemented from the following published paper:" << endl;
126 cout <<
"B. De Man and S. Basu, \"Distance-driven projection and backprojection in three dimensions\", Phys. Med. Biol., vol. 49, pp. 2463-75, 2004." << endl;
127 cout <<
"There is 1 optional parameter for this projector:" << endl;
128 cout <<
" tolerance_factor: x. -> 'x' must be an unsigned integer, and represent the tolerance precision factor for plane index computation (10^(-x))." << endl;
129 cout <<
" -> Default: 'x' = 6" << endl;
142 Cerr(
"***** iProjectorJoseph::CheckSpecificParameters() -> Tolerance factor must be defined in the specific interval : ]0 ; 1.e-2]" << endl);
143 Cerr(
"***** -> Default value is 1.e-6" << endl);
160 if (
m_verbose>=2)
Cout(
"iProjectorDistanceDriven::InitializeSpecific() -> Use Distance Driven projector" << endl);
192 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> Called while not initialized !" << endl);
197 #ifdef CASTOR_VERBOSE 200 string direction =
"";
201 if (a_direction==
FORWARD) direction =
"forward";
202 else direction =
"backward";
203 Cout(
"iProjectorDistanceDriven::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
261 &p1_x[1], &p1_y[1], &p1_z[1],
262 &p2_x[1], &p2_y[1], &p2_z[1]
265 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> A problem occurred while getting the edges' center positions !" << endl);
276 p1_x[ 0 ] = p1[ 0 ]; p1_y[ 0 ] = p1[ 1 ]; p1_z[ 0 ] = p1[ 2 ];
279 p2_x[ 0 ] = p2[ 0 ]; p2_y[ 0 ] = p2[ 1 ]; p2_z[ 0 ] = p2[ 2 ];
288 for(
int p = 0; p < 5; ++p )
290 r[ p ][ 0 ] = p2_x[ p ] - p1_x[ p ];
291 r[ p ][ 1 ] = p2_y[ p ] - p1_y[ p ];
292 r[ p ][ 2 ] = p2_z[ p ] - p1_z[ p ];
297 r[ 0 ][ 0 ] * r[ 0 ][ 0 ],
298 r[ 0 ][ 1 ] * r[ 0 ][ 1 ],
299 r[ 0 ][ 2 ] * r[ 0 ][ 2 ]
304 HPFLTNB alpha_min = 0.0, alpha_max = 1.0;
308 HPFLTNB alpha_x_min[ 4 ], alpha_x_max[ 4 ];
309 HPFLTNB alpha_y_min[ 4 ], alpha_y_max[ 4 ];
310 HPFLTNB alpha_z_min[ 4 ], alpha_z_max[ 4 ];
335 float const angle = std::acos( ( r[ 0 ][ 0 ] ) / ( std::sqrt( r2[ 0 ] + r2[ 1 ] ) ) ) * 180.0f / M_PI;
338 if( ( angle >= 0.0 && angle <= 45.0 ) || ( angle >= 135.0 && angle <= 180.0 ) )
342 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
343 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
344 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
345 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
346 alpha_min = std::max( alpha_min, std::min( alpha_x_min[ 0 ], alpha_x_min[ 1 ] ) );
347 alpha_max = std::min( alpha_max, std::max( alpha_x_max[ 0 ], alpha_x_max[ 1 ] ) );
351 if( r[ 1 ][ 1 ] != 0.0 )
353 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
354 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
355 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
356 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
360 alpha_y_min[ 0 ] = 0.0;
361 alpha_y_min[ 1 ] = 0.0;
362 alpha_y_max[ 0 ] = 1.0;
363 alpha_y_max[ 1 ] = 1.0;
366 if( r[ 2 ][ 1 ] != 0.0 )
368 alpha_y_min[ 2 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
369 alpha_y_min[ 3 ] = (
mp_halfFOV[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
370 alpha_y_max[ 2 ] = alpha_y_min[ 2 ];
371 alpha_y_max[ 3 ] = alpha_y_min[ 3 ];
375 alpha_y_min[ 2 ] = 0.0;
376 alpha_y_min[ 3 ] = 0.0;
377 alpha_y_max[ 2 ] = 1.0;
378 alpha_y_max[ 3 ] = 1.0;
382 alpha_min = std::max( alpha_min,
383 alpha_y_min[ std::minmax_element( alpha_y_min, alpha_y_min + 4 ).first - alpha_y_min ] );
385 alpha_max = std::min( alpha_max,
386 alpha_y_max[ std::minmax_element( alpha_y_max, alpha_y_max + 4 ).second - alpha_y_max ] );
389 if( r[ 3 ][ 2 ] != 0.0 )
391 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
392 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
393 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
394 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
398 alpha_z_min[ 0 ] = 0.0;
399 alpha_z_min[ 1 ] = 0.0;
400 alpha_z_max[ 0 ] = 1.0;
401 alpha_z_max[ 1 ] = 1.0;
404 if( r[ 4 ][ 2 ] != 0.0 )
406 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
407 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
408 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
409 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
413 alpha_z_min[ 2 ] = 0.0;
414 alpha_z_min[ 3 ] = 0.0;
415 alpha_z_max[ 2 ] = 1.0;
416 alpha_z_max[ 3 ] = 1.0;
420 alpha_min = std::max( alpha_min,
421 alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first
424 alpha_max = std::min( alpha_max,
425 alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second
428 if( alpha_max <= alpha_min )
return 0;
431 int16_t i_min = 0, i_max = 0;
432 if( r[ 0 ][ 0 ] > 0.0 )
437 else if( r[ 0 ][ 0 ] < 0.0 )
445 HPFLTNB const factor( ::fabs( r[ 0 ][ 0 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
450 for( uint8_t p = 0; p < 4; ++p )
453 ri[ p ][ 1 ] = r[ p + 1 ][ 1 ] / r[ p + 1 ][ 0 ];
454 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 0 ];
458 int8_t incr_orient_trans = 0;
459 int8_t idx_orient_trans = 0;
462 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
466 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
472 for( int16_t i = i_min; i < i_max; ++i )
477 pos[ 0 ] = p1_y[ 1 ] + step * ri[ 0 ][ 1 ];
478 pos[ 1 ] = p1_y[ 2 ] + step * ri[ 1 ][ 1 ];
480 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
481 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
484 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
485 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
487 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
500 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
504 if( index[ 0 ] < index[ 1 ] )
506 incr_orient_trans = 1;
507 idx_orient_trans = 1;
509 else if( index[ 0 ] > index[ 1 ] )
511 incr_orient_trans = -1;
512 idx_orient_trans = 0;
516 int16_t
const n_distance_y = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
518 distance_y[ 0 ] = pos[ 0 ];
519 distance_y[ n_distance_y - 1 ] = pos[ 1 ];
521 if( n_distance_y > 2 )
523 for( int16_t d = 0; d < n_distance_y - 2; ++d )
524 distance_y[ d + 1 ] = (-
mp_halfFOV[ 1 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 1 ];
528 for( int16_t d = 0; d < n_distance_y - 1; ++d )
529 distance_y[ d ] = ::fabs( distance_y[ d + 1 ] - distance_y[ d ] );
532 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
534 distance_z[ 0 ] = pos[ 2 ];
535 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
537 if( n_distance_z > 2 )
539 for( int16_t d = 0; d < n_distance_z - 2; ++d )
540 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
544 for( int16_t d = 0; d < n_distance_z - 1; ++d )
545 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
548 int16_t index_y, index_z;
549 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
551 index_z = index[ 2 ] + jj * incr_orient_axial;
552 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
554 for( int16_t ii = 0; ii < n_distance_y - 1; ++ii )
556 index_y = index[ 0 ] + ii * incr_orient_trans;
557 if( index_y < 0 || index_y >
mp_nbVox[ 1 ] - 1 )
continue;
559 ap_ProjectionLine->
AddVoxel(a_direction, i + index_y *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_y[ ii ]);
568 if( r[ 1 ][ 0 ] != 0.0 )
570 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
571 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
572 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
573 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
577 alpha_x_min[ 0 ] = 0.0;
578 alpha_x_min[ 1 ] = 0.0;
579 alpha_x_max[ 0 ] = 1.0;
580 alpha_x_max[ 1 ] = 1.0;
583 if( r[ 2 ][ 0 ] != 0.0 )
585 alpha_x_min[ 2 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
586 alpha_x_min[ 3 ] = (
mp_halfFOV[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
587 alpha_x_max[ 2 ] = alpha_x_min[ 2 ];
588 alpha_x_max[ 3 ] = alpha_x_min[ 3 ];
592 alpha_x_min[ 2 ] = 0.0;
593 alpha_x_min[ 3 ] = 0.0;
594 alpha_x_max[ 2 ] = 1.0;
595 alpha_x_max[ 3 ] = 1.0;
599 alpha_min = std::max( alpha_min,
600 alpha_x_min[ std::minmax_element( alpha_x_min, alpha_x_min + 4 ).first - alpha_x_min ] );
602 alpha_max = std::min( alpha_max,
603 alpha_x_max[ std::minmax_element( alpha_x_max, alpha_x_max + 4 ).second - alpha_x_max ] );
607 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
608 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
609 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
610 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
611 alpha_min = std::max( alpha_min,
612 std::min( alpha_y_min[ 0 ], alpha_y_min[ 1 ] ) );
613 alpha_max = std::min( alpha_max,
614 std::max( alpha_y_max[ 0 ], alpha_y_max[ 1 ] ) );
617 if( r[ 3 ][ 2 ] != 0.0 )
619 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
620 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
621 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
622 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
626 alpha_z_min[ 0 ] = 0.0;
627 alpha_z_min[ 1 ] = 0.0;
628 alpha_z_max[ 0 ] = 1.0;
629 alpha_z_max[ 1 ] = 1.0;
632 if( r[ 4 ][ 2 ] != 0.0 )
634 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
635 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
636 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
637 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
641 alpha_z_min[ 2 ] = 0.0;
642 alpha_z_min[ 3 ] = 0.0;
643 alpha_z_max[ 2 ] = 1.0;
644 alpha_z_max[ 3 ] = 1.0;
648 alpha_min = std::max( alpha_min, alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first - alpha_z_min ] );
650 alpha_max = std::min( alpha_max, alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second - alpha_z_max ] );
652 if( alpha_max <= alpha_min )
return 0;
655 int16_t j_min = 0, j_max = 0;
656 if( r[ 0 ][ 1 ] > 0.0 )
661 else if( r[ 0 ][ 1 ] < 0.0 )
669 HPFLTNB const factor( ::fabs( r[ 0 ][ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
674 for( uint8_t p = 0; p < 4; ++p )
676 ri[ p ][ 0 ] = r[ p + 1 ][ 0 ] / r[ p + 1 ][ 1 ];
678 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 1 ];
682 int8_t incr_orient_trans = 0;
683 int8_t idx_orient_trans = 0;
686 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
688 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
694 for( int16_t j = j_min; j < j_max; ++j )
699 pos[ 0 ] = p1_x[ 1 ] + step * ri[ 0 ][ 0 ];
700 pos[ 1 ] = p1_x[ 2 ] + step * ri[ 1 ][ 0 ];
702 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
703 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
706 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
707 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
709 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
722 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
726 if( index[ 0 ] < index[ 1 ] )
728 incr_orient_trans = 1;
729 idx_orient_trans = 1;
731 else if( index[ 0 ] > index[ 1 ] )
733 incr_orient_trans = -1;
734 idx_orient_trans = 0;
738 int16_t
const n_distance_x = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
740 distance_x[ 0 ] = pos[ 0 ];
741 distance_x[ n_distance_x - 1 ] = pos[ 1 ];
743 if( n_distance_x > 2 )
745 for( int16_t d = 0; d < n_distance_x - 2; ++d )
746 distance_x[ d + 1 ] = (-
mp_halfFOV[ 0 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 0 ];
750 for( int16_t d = 0; d < n_distance_x - 1; ++d )
751 distance_x[ d ] = ::fabs( distance_x[ d + 1 ] - distance_x[ d ] );
754 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
756 distance_z[ 0 ] = pos[ 2 ];
757 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
759 if( n_distance_z > 2 )
761 for( int16_t d = 0; d < n_distance_z - 2; ++d )
762 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
766 for( int16_t d = 0; d < n_distance_z - 1; ++d )
767 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
770 int16_t index_x, index_z;
771 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
773 index_z = index[ 2 ] + jj * incr_orient_axial;
774 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
776 for( int16_t ii = 0; ii < n_distance_x - 1; ++ii )
778 index_x = index[ 0 ] + ii * incr_orient_trans;
779 if( index_x < 0 || index_x >
mp_nbVox[ 0 ] - 1 )
continue;
781 ap_ProjectionLine->
AddVoxel(a_direction, index_x + j *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_x[ ii ]);
800 Cerr(
"***** iProjectorDistanceDriven::ProjectTOFListmode() -> Called while not initialized !" << endl);
805 #ifdef CASTOR_VERBOSE 808 string direction =
"";
809 if (a_direction==
FORWARD) direction =
"forward";
810 else direction =
"backward";
811 Cout(
"iProjectorDistanceDriven::Project with TOF measurement -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
868 &p1_x[1], &p1_y[1], &p1_z[1],
869 &p2_x[1], &p2_y[1], &p2_z[1]
872 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> A problem occurred while getting the edges' center positions !" << endl);
883 p1_x[ 0 ] = p1[ 0 ]; p1_y[ 0 ] = p1[ 1 ]; p1_z[ 0 ] = p1[ 2 ];
886 p2_x[ 0 ] = p2[ 0 ]; p2_y[ 0 ] = p2[ 1 ]; p2_z[ 0 ] = p2[ 2 ];
895 for(
int p = 0; p < 5; ++p )
897 r[ p ][ 0 ] = p2_x[ p ] - p1_x[ p ];
898 r[ p ][ 1 ] = p2_y[ p ] - p1_y[ p ];
899 r[ p ][ 2 ] = p2_z[ p ] - p1_z[ p ];
904 r[ 0 ][ 0 ] * r[ 0 ][ 0 ],
905 r[ 0 ][ 1 ] * r[ 0 ][ 1 ],
906 r[ 0 ][ 2 ] * r[ 0 ][ 2 ]
911 HPFLTNB alpha_min = 0.0, alpha_max = 1.0;
915 HPFLTNB alpha_x_min[ 4 ], alpha_x_max[ 4 ];
916 HPFLTNB alpha_y_min[ 4 ], alpha_y_max[ 4 ];
917 HPFLTNB alpha_z_min[ 4 ], alpha_z_max[ 4 ];
951 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
959 HPFLTNB lor_tof_center = length_LOR * 0.5 + tof_delta;
962 HPFLTNB tof_edge_low[] = {0,0,0};
964 HPFLTNB tof_edge_high[] = {0,0,0};
965 HPFLTNB tof_center[] = {0,0,0};
969 for (
int ax=0;ax<3;ax++)
972 tof_center[ax] = p1[ax] + lor_tof_center * r[0][ax] / length_LOR;
975 tof_edge_low[ax] = tof_center[ax] - tof_half_span * fabs(r[0][ax]) / length_LOR;
978 if (tof_index>
mp_nbVox[ax]-1)
return 0;
982 tof_edge_high[ax] = tof_center[ax] + tof_half_span * fabs(r[0][ax]) / length_LOR;
985 if (tof_index<0)
return 0;
990 float const angle = std::acos( ( r[ 0 ][ 0 ] ) / ( std::sqrt( r2[ 0 ] + r2[ 1 ] ) ) ) * 180.0f / M_PI;
993 if( ( angle >= 0.0 && angle <= 45.0 ) || ( angle >= 135.0 && angle <= 180.0 ) )
998 alpha_x_min[ 0 ] = ( tof_edge_low[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
999 alpha_x_min[ 1 ] = ( tof_edge_high[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
1000 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
1001 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
1002 alpha_min = std::max( alpha_min, std::min( alpha_x_min[ 0 ], alpha_x_min[ 1 ] ) );
1003 alpha_max = std::min( alpha_max, std::max( alpha_x_max[ 0 ], alpha_x_max[ 1 ] ) );
1007 if( r[ 1 ][ 1 ] != 0 )
1009 alpha_y_min[ 0 ] = ( tof_edge_low[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
1010 alpha_y_min[ 1 ] = ( tof_edge_high[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
1011 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
1012 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
1016 alpha_y_min[ 0 ] = 0.0;
1017 alpha_y_min[ 1 ] = 0.0;
1018 alpha_y_max[ 0 ] = 1.0;
1019 alpha_y_max[ 1 ] = 1.0;
1022 if( r[ 2 ][ 1 ] != 0 )
1024 alpha_y_min[ 2 ] = ( tof_edge_low[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
1025 alpha_y_min[ 3 ] = ( tof_edge_high[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
1026 alpha_y_max[ 2 ] = alpha_y_min[ 2 ];
1027 alpha_y_max[ 3 ] = alpha_y_min[ 3 ];
1031 alpha_y_min[ 2 ] = 0.0;
1032 alpha_y_min[ 3 ] = 0.0;
1033 alpha_y_max[ 2 ] = 1.0;
1034 alpha_y_max[ 3 ] = 1.0;
1038 alpha_min = std::max( alpha_min,
1039 alpha_y_min[ std::minmax_element( alpha_y_min, alpha_y_min + 4 ).first - alpha_y_min ] );
1041 alpha_max = std::min( alpha_max,
1042 alpha_y_max[ std::minmax_element( alpha_y_max, alpha_y_max + 4 ).second - alpha_y_max ] );
1045 if( r[ 3 ][ 2 ] != 0 )
1047 alpha_z_min[ 0 ] = ( tof_edge_low[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1048 alpha_z_min[ 1 ] = ( tof_edge_high[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1049 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1050 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1054 alpha_z_min[ 0 ] = 0.0;
1055 alpha_z_min[ 1 ] = 0.0;
1056 alpha_z_max[ 0 ] = 1.0;
1057 alpha_z_max[ 1 ] = 1.0;
1060 if( r[ 4 ][ 2 ] != 0 )
1062 alpha_z_min[ 2 ] = ( tof_edge_low[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1063 alpha_z_min[ 3 ] = ( tof_edge_high[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1064 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1065 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1069 alpha_z_min[ 2 ] = 0.0;
1070 alpha_z_min[ 3 ] = 0.0;
1071 alpha_z_max[ 2 ] = 1.0;
1072 alpha_z_max[ 3 ] = 1.0;
1076 alpha_min = std::max( alpha_min,
1077 alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first
1080 alpha_max = std::min( alpha_max,
1081 alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second
1084 if( alpha_max <= alpha_min )
return 0;
1087 int16_t i_min = 0, i_max = 0;
1088 if( r[ 0 ][ 0 ] > 0.0 )
1093 else if( r[ 0 ][ 0 ] < 0.0 )
1101 HPFLTNB const factor( ::fabs( r[ 0 ][ 0 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
1103 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 0 ] );
1107 for( uint8_t p = 0; p < 4; ++p )
1110 ri[ p ][ 1 ] = r[ p + 1 ][ 1 ] / r[ p + 1 ][ 0 ];
1111 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 0 ];
1115 int8_t incr_orient_trans = 0;
1116 int8_t idx_orient_trans = 0;
1119 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
1123 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
1129 for( int16_t i = i_min; i < i_max; ++i )
1134 pos[ 0 ] = p1_y[ 1 ] + step * ri[ 0 ][ 1 ];
1135 pos[ 1 ] = p1_y[ 2 ] + step * ri[ 1 ][ 1 ];
1137 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
1138 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
1141 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
1142 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
1144 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
1157 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
1161 if( index[ 0 ] < index[ 1 ] )
1163 incr_orient_trans = 1;
1164 idx_orient_trans = 1;
1166 else if( index[ 0 ] > index[ 1 ] )
1168 incr_orient_trans = -1;
1169 idx_orient_trans = 0;
1173 int16_t
const n_distance_y = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
1175 distance_y[ 0 ] = pos[ 0 ];
1176 distance_y[ n_distance_y - 1 ] = pos[ 1 ];
1178 if( n_distance_y > 2 )
1180 for( int16_t d = 0; d < n_distance_y - 2; ++d )
1181 distance_y[ d + 1 ] = (-
mp_halfFOV[ 1 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 1 ];
1185 for( int16_t d = 0; d < n_distance_y - 1; ++d )
1186 distance_y[ d ] = ::fabs( distance_y[ d + 1 ] - distance_y[ d ] );
1189 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
1191 distance_z[ 0 ] = pos[ 2 ];
1192 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
1194 if( n_distance_z > 2 )
1196 for( int16_t d = 0; d < n_distance_z - 2; ++d )
1197 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
1201 for( int16_t d = 0; d < n_distance_z - 1; ++d )
1202 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
1219 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - step * factor_for_tof));
1220 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
1221 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - step * factor_for_tof));
1222 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
1229 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
1235 int16_t index_y, index_z;
1236 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
1238 index_z = index[ 2 ] + jj * incr_orient_axial;
1239 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
1241 for( int16_t ii = 0; ii < n_distance_y - 1; ++ii )
1243 index_y = index[ 0 ] + ii * incr_orient_trans;
1244 if( index_y < 0 || index_y >
mp_nbVox[ 1 ] - 1 )
continue;
1246 ap_ProjectionLine->
AddVoxel(a_direction, i + index_y *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_y[ ii ] * tof_weight);
1256 if( r[ 1 ][ 0 ] != 0.0 )
1258 alpha_x_min[ 0 ] = ( tof_edge_low[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
1259 alpha_x_min[ 1 ] = ( tof_edge_high[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
1260 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
1261 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
1265 alpha_x_min[ 0 ] = 0.0;
1266 alpha_x_min[ 1 ] = 0.0;
1267 alpha_x_max[ 0 ] = 1.0;
1268 alpha_x_max[ 1 ] = 1.0;
1271 if( r[ 2 ][ 0 ] != 0 )
1273 alpha_x_min[ 2 ] = ( tof_edge_low[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
1274 alpha_x_min[ 3 ] = ( tof_edge_high[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
1275 alpha_x_max[ 2 ] = alpha_x_min[ 2 ];
1276 alpha_x_max[ 3 ] = alpha_x_min[ 3 ];
1280 alpha_x_min[ 2 ] = 0.0;
1281 alpha_x_min[ 3 ] = 0.0;
1282 alpha_x_max[ 2 ] = 1.0;
1283 alpha_x_max[ 3 ] = 1.0;
1287 alpha_min = std::max( alpha_min,
1288 alpha_x_min[ std::minmax_element( alpha_x_min, alpha_x_min + 4 ).first - alpha_x_min ] );
1290 alpha_max = std::min( alpha_max,
1291 alpha_x_max[ std::minmax_element( alpha_x_max, alpha_x_max + 4 ).second - alpha_x_max ] );
1295 alpha_y_min[ 0 ] = ( tof_edge_low[1] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
1296 alpha_y_min[ 1 ] = ( tof_edge_high[1] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
1297 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
1298 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
1299 alpha_min = std::max( alpha_min,
1300 std::min( alpha_y_min[ 0 ], alpha_y_min[ 1 ] ) );
1301 alpha_max = std::min( alpha_max,
1302 std::max( alpha_y_max[ 0 ], alpha_y_max[ 1 ] ) );
1305 if( r[ 3 ][ 2 ] != 0 )
1307 alpha_z_min[ 0 ] = ( tof_edge_low[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1308 alpha_z_min[ 1 ] = ( tof_edge_high[ 2 ]- p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1309 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1310 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1314 alpha_z_min[ 0 ] = 0.0;
1315 alpha_z_min[ 1 ] = 0.0;
1316 alpha_z_max[ 0 ] = 1.0;
1317 alpha_z_max[ 1 ] = 1.0;
1320 if( r[ 4 ][ 2 ] != 0 )
1322 alpha_z_min[ 2 ] = ( tof_edge_low[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1323 alpha_z_min[ 3 ] = ( tof_edge_high[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1324 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1325 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1329 alpha_z_min[ 2 ] = 0.0;
1330 alpha_z_min[ 3 ] = 0.0;
1331 alpha_z_max[ 2 ] = 1.0;
1332 alpha_z_max[ 3 ] = 1.0;
1336 alpha_min = std::max( alpha_min, alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first - alpha_z_min ] );
1338 alpha_max = std::min( alpha_max, alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second - alpha_z_max ] );
1340 if( alpha_max <= alpha_min )
return 0;
1343 int16_t j_min = 0, j_max = 0;
1344 if( r[ 0 ][ 1 ] > 0.0 )
1349 else if( r[ 0 ][ 1 ] < 0.0 )
1357 HPFLTNB const factor( ::fabs( r[ 0 ][ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
1359 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 1 ] );
1363 for( uint8_t p = 0; p < 4; ++p )
1365 ri[ p ][ 0 ] = r[ p + 1 ][ 0 ] / r[ p + 1 ][ 1 ];
1367 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 1 ];
1371 int8_t incr_orient_trans = 0;
1372 int8_t idx_orient_trans = 0;
1375 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
1377 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
1383 for( int16_t j = j_min; j < j_max; ++j )
1388 pos[ 0 ] = p1_x[ 1 ] + step * ri[ 0 ][ 0 ];
1389 pos[ 1 ] = p1_x[ 2 ] + step * ri[ 1 ][ 0 ];
1391 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
1392 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
1395 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
1396 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
1398 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
1411 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
1415 if( index[ 0 ] < index[ 1 ] )
1417 incr_orient_trans = 1;
1418 idx_orient_trans = 1;
1420 else if( index[ 0 ] > index[ 1 ] )
1422 incr_orient_trans = -1;
1423 idx_orient_trans = 0;
1427 int16_t
const n_distance_x = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
1429 distance_x[ 0 ] = pos[ 0 ];
1430 distance_x[ n_distance_x - 1 ] = pos[ 1 ];
1432 if( n_distance_x > 2 )
1434 for( int16_t d = 0; d < n_distance_x - 2; ++d )
1435 distance_x[ d + 1 ] = (-
mp_halfFOV[ 0 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 0 ];
1439 for( int16_t d = 0; d < n_distance_x - 1; ++d )
1440 distance_x[ d ] = ::fabs( distance_x[ d + 1 ] - distance_x[ d ] );
1443 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
1445 distance_z[ 0 ] = pos[ 2 ];
1446 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
1448 if( n_distance_z > 2 )
1450 for( int16_t d = 0; d < n_distance_z - 2; ++d )
1451 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
1455 for( int16_t d = 0; d < n_distance_z - 1; ++d )
1456 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
1473 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - step * factor_for_tof));
1474 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
1475 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - step * factor_for_tof));
1476 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
1483 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
1489 int16_t index_x, index_z;
1490 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
1492 index_z = index[ 2 ] + jj * incr_orient_axial;
1493 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
1495 for( int16_t ii = 0; ii < n_distance_x - 1; ++ii )
1497 index_x = index[ 0 ] + ii * incr_orient_trans;
1498 if( index_x < 0 || index_x >
mp_nbVox[ 0 ] - 1 )
continue;
1500 ap_ProjectionLine->
AddVoxel(a_direction, index_x + j *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_x[ ii ] * tof_weight);
1519 Cerr(
"***** iProjectorDistanceDriven::ProjectTOFHistogram() -> Called while not initialized !" << endl);
1524 #ifdef CASTOR_VERBOSE 1527 string direction =
"";
1528 if (a_direction==
FORWARD) direction =
"forward";
1529 else direction =
"backward";
1530 Cout(
"iProjectorDistanceDriven::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
1576 HPFLTNB length_LOR_half = length_LOR * 0.5;
1580 INTNB tof_half_nb_bins = tof_nb_bins/2;
1584 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
1590 HPFLTNB prev_erf = 0., new_erf = 0.;
1593 INTNB tof_bin_last = tof_half_nb_bins;
1594 INTNB tof_bin_first = -tof_half_nb_bins;
1602 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
1618 &p1_x[1], &p1_y[1], &p1_z[1],
1619 &p2_x[1], &p2_y[1], &p2_z[1]
1622 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> A problem occurred while getting the edges' center positions !" << endl);
1633 p1_x[ 0 ] = p1[ 0 ]; p1_y[ 0 ] = p1[ 1 ]; p1_z[ 0 ] = p1[ 2 ];
1636 p2_x[ 0 ] = p2[ 0 ]; p2_y[ 0 ] = p2[ 1 ]; p2_z[ 0 ] = p2[ 2 ];
1645 for(
int p = 0; p < 5; ++p )
1647 r[ p ][ 0 ] = p2_x[ p ] - p1_x[ p ];
1648 r[ p ][ 1 ] = p2_y[ p ] - p1_y[ p ];
1649 r[ p ][ 2 ] = p2_z[ p ] - p1_z[ p ];
1654 r[ 0 ][ 0 ] * r[ 0 ][ 0 ],
1655 r[ 0 ][ 1 ] * r[ 0 ][ 1 ],
1656 r[ 0 ][ 2 ] * r[ 0 ][ 2 ]
1661 HPFLTNB alpha_min = 0.0, alpha_max = 1.0;
1665 HPFLTNB alpha_x_min[ 4 ], alpha_x_max[ 4 ];
1666 HPFLTNB alpha_y_min[ 4 ], alpha_y_max[ 4 ];
1667 HPFLTNB alpha_z_min[ 4 ], alpha_z_max[ 4 ];
1692 float const angle = std::acos( ( r[ 0 ][ 0 ] ) / ( std::sqrt( r2[ 0 ] + r2[ 1 ] ) ) ) * 180.0f / M_PI;
1695 if( ( angle >= 0.0 && angle <= 45.0 ) || ( angle >= 135.0 && angle <= 180.0 ) )
1699 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
1700 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
1701 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
1702 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
1703 alpha_min = std::max( alpha_min, std::min( alpha_x_min[ 0 ], alpha_x_min[ 1 ] ) );
1704 alpha_max = std::min( alpha_max, std::max( alpha_x_max[ 0 ], alpha_x_max[ 1 ] ) );
1708 if( r[ 1 ][ 1 ] != 0.0 )
1710 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
1711 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
1712 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
1713 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
1717 alpha_y_min[ 0 ] = 0.0;
1718 alpha_y_min[ 1 ] = 0.0;
1719 alpha_y_max[ 0 ] = 1.0;
1720 alpha_y_max[ 1 ] = 1.0;
1723 if( r[ 2 ][ 1 ] != 0.0 )
1725 alpha_y_min[ 2 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
1726 alpha_y_min[ 3 ] = (
mp_halfFOV[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
1727 alpha_y_max[ 2 ] = alpha_y_min[ 2 ];
1728 alpha_y_max[ 3 ] = alpha_y_min[ 3 ];
1732 alpha_y_min[ 2 ] = 0.0;
1733 alpha_y_min[ 3 ] = 0.0;
1734 alpha_y_max[ 2 ] = 1.0;
1735 alpha_y_max[ 3 ] = 1.0;
1739 alpha_min = std::max( alpha_min,
1740 alpha_y_min[ std::minmax_element( alpha_y_min, alpha_y_min + 4 ).first - alpha_y_min ] );
1742 alpha_max = std::min( alpha_max,
1743 alpha_y_max[ std::minmax_element( alpha_y_max, alpha_y_max + 4 ).second - alpha_y_max ] );
1746 if( r[ 3 ][ 2 ] != 0.0 )
1748 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1749 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1750 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1751 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1755 alpha_z_min[ 0 ] = 0.0;
1756 alpha_z_min[ 1 ] = 0.0;
1757 alpha_z_max[ 0 ] = 1.0;
1758 alpha_z_max[ 1 ] = 1.0;
1761 if( r[ 4 ][ 2 ] != 0.0 )
1763 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1764 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1765 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1766 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1770 alpha_z_min[ 2 ] = 0.0;
1771 alpha_z_min[ 3 ] = 0.0;
1772 alpha_z_max[ 2 ] = 1.0;
1773 alpha_z_max[ 3 ] = 1.0;
1777 alpha_min = std::max( alpha_min,
1778 alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first
1781 alpha_max = std::min( alpha_max,
1782 alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second
1785 if( alpha_max <= alpha_min )
return 0;
1790 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1793 int16_t i_min = 0, i_max = 0;
1794 if( r[ 0 ][ 0 ] > 0.0 )
1799 else if( r[ 0 ][ 0 ] < 0.0 )
1807 HPFLTNB const factor( ::fabs( r[ 0 ][ 0 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
1808 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 0 ] );
1813 for( uint8_t p = 0; p < 4; ++p )
1816 ri[ p ][ 1 ] = r[ p + 1 ][ 1 ] / r[ p + 1 ][ 0 ];
1817 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 0 ];
1821 int8_t incr_orient_trans = 0;
1822 int8_t idx_orient_trans = 0;
1825 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
1829 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
1835 for( int16_t i = i_min; i < i_max; ++i )
1840 pos[ 0 ] = p1_y[ 1 ] + step * ri[ 0 ][ 1 ];
1841 pos[ 1 ] = p1_y[ 2 ] + step * ri[ 1 ][ 1 ];
1843 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
1844 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
1847 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
1848 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
1850 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
1863 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
1867 if( index[ 0 ] < index[ 1 ] )
1869 incr_orient_trans = 1;
1870 idx_orient_trans = 1;
1872 else if( index[ 0 ] > index[ 1 ] )
1874 incr_orient_trans = -1;
1875 idx_orient_trans = 0;
1879 int16_t
const n_distance_y = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
1881 distance_y[ 0 ] = pos[ 0 ];
1882 distance_y[ n_distance_y - 1 ] = pos[ 1 ];
1884 if( n_distance_y > 2 )
1886 for( int16_t d = 0; d < n_distance_y - 2; ++d )
1887 distance_y[ d + 1 ] = (-
mp_halfFOV[ 1 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 1 ];
1891 for( int16_t d = 0; d < n_distance_y - 1; ++d )
1892 distance_y[ d ] = ::fabs( distance_y[ d + 1 ] - distance_y[ d ] );
1895 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
1897 distance_z[ 0 ] = pos[ 2 ];
1898 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
1900 if( n_distance_z > 2 )
1902 for( int16_t d = 0; d < n_distance_z - 2; ++d )
1903 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
1907 for( int16_t d = 0; d < n_distance_z - 1; ++d )
1908 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
1920 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (step * factor_for_tof - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
1921 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (step * factor_for_tof + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
1924 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1927 tof_bin_first_for_voxel += tof_half_nb_bins;
1928 tof_bin_last_for_voxel += tof_half_nb_bins;
1934 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - step * factor_for_tof));
1935 prev_erf = erf(temp/tof_sigma_sqrt2);
1940 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1960 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - step * factor_for_tof));
1961 new_erf = erf(temp/tof_sigma_sqrt2);
1962 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1972 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
1991 int16_t index_y, index_z;
1992 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
1994 index_z = index[ 2 ] + jj * incr_orient_axial;
1995 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
1997 for( int16_t ii = 0; ii < n_distance_y - 1; ++ii )
1999 index_y = index[ 0 ] + ii * incr_orient_trans;
2000 if( index_y < 0 || index_y >
mp_nbVox[ 1 ] - 1 )
continue;
2002 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, i + index_y *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_y[ ii ], tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
2006 delete[] tof_weights_temp;
2012 if( r[ 1 ][ 0 ] != 0.0 )
2014 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
2015 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
2016 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
2017 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
2021 alpha_x_min[ 0 ] = 0.0;
2022 alpha_x_min[ 1 ] = 0.0;
2023 alpha_x_max[ 0 ] = 1.0;
2024 alpha_x_max[ 1 ] = 1.0;
2027 if( r[ 2 ][ 0 ] != 0.0 )
2029 alpha_x_min[ 2 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
2030 alpha_x_min[ 3 ] = (
mp_halfFOV[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
2031 alpha_x_max[ 2 ] = alpha_x_min[ 2 ];
2032 alpha_x_max[ 3 ] = alpha_x_min[ 3 ];
2036 alpha_x_min[ 2 ] = 0.0;
2037 alpha_x_min[ 3 ] = 0.0;
2038 alpha_x_max[ 2 ] = 1.0;
2039 alpha_x_max[ 3 ] = 1.0;
2043 alpha_min = std::max( alpha_min,
2044 alpha_x_min[ std::minmax_element( alpha_x_min, alpha_x_min + 4 ).first - alpha_x_min ] );
2046 alpha_max = std::min( alpha_max,
2047 alpha_x_max[ std::minmax_element( alpha_x_max, alpha_x_max + 4 ).second - alpha_x_max ] );
2051 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
2052 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
2053 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
2054 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
2055 alpha_min = std::max( alpha_min,
2056 std::min( alpha_y_min[ 0 ], alpha_y_min[ 1 ] ) );
2057 alpha_max = std::min( alpha_max,
2058 std::max( alpha_y_max[ 0 ], alpha_y_max[ 1 ] ) );
2061 if( r[ 3 ][ 2 ] != 0.0 )
2063 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
2064 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
2065 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
2066 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
2070 alpha_z_min[ 0 ] = 0.0;
2071 alpha_z_min[ 1 ] = 0.0;
2072 alpha_z_max[ 0 ] = 1.0;
2073 alpha_z_max[ 1 ] = 1.0;
2076 if( r[ 4 ][ 2 ] != 0.0 )
2078 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
2079 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
2080 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
2081 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
2085 alpha_z_min[ 2 ] = 0.0;
2086 alpha_z_min[ 3 ] = 0.0;
2087 alpha_z_max[ 2 ] = 1.0;
2088 alpha_z_max[ 3 ] = 1.0;
2092 alpha_min = std::max( alpha_min, alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first - alpha_z_min ] );
2094 alpha_max = std::min( alpha_max, alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second - alpha_z_max ] );
2096 if( alpha_max <= alpha_min )
return 0;
2101 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
2104 int16_t j_min = 0, j_max = 0;
2105 if( r[ 0 ][ 1 ] > 0.0 )
2110 else if( r[ 0 ][ 1 ] < 0.0 )
2118 HPFLTNB const factor( ::fabs( r[ 0 ][ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
2119 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 1 ] );
2124 for( uint8_t p = 0; p < 4; ++p )
2126 ri[ p ][ 0 ] = r[ p + 1 ][ 0 ] / r[ p + 1 ][ 1 ];
2128 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 1 ];
2132 int8_t incr_orient_trans = 0;
2133 int8_t idx_orient_trans = 0;
2136 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
2138 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
2144 for( int16_t j = j_min; j < j_max; ++j )
2149 pos[ 0 ] = p1_x[ 1 ] + step * ri[ 0 ][ 0 ];
2150 pos[ 1 ] = p1_x[ 2 ] + step * ri[ 1 ][ 0 ];
2152 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
2153 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
2156 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
2157 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
2159 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
2171 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
2175 if( index[ 0 ] < index[ 1 ] )
2177 incr_orient_trans = 1;
2178 idx_orient_trans = 1;
2180 else if( index[ 0 ] > index[ 1 ] )
2182 incr_orient_trans = -1;
2183 idx_orient_trans = 0;
2187 int16_t
const n_distance_x = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
2189 distance_x[ 0 ] = pos[ 0 ];
2190 distance_x[ n_distance_x - 1 ] = pos[ 1 ];
2192 if( n_distance_x > 2 )
2194 for( int16_t d = 0; d < n_distance_x - 2; ++d )
2195 distance_x[ d + 1 ] = (-
mp_halfFOV[ 0 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 0 ];
2199 for( int16_t d = 0; d < n_distance_x - 1; ++d )
2200 distance_x[ d ] = ::fabs( distance_x[ d + 1 ] - distance_x[ d ] );
2203 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
2205 distance_z[ 0 ] = pos[ 2 ];
2206 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
2208 if( n_distance_z > 2 )
2210 for( int16_t d = 0; d < n_distance_z - 2; ++d )
2211 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
2215 for( int16_t d = 0; d < n_distance_z - 1; ++d )
2216 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
2228 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (step * factor_for_tof - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
2229 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (step * factor_for_tof + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
2232 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
2235 tof_bin_first_for_voxel += tof_half_nb_bins;
2236 tof_bin_last_for_voxel += tof_half_nb_bins;
2242 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - step * factor_for_tof));
2243 prev_erf = erf(temp/tof_sigma_sqrt2);
2248 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
2268 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - step * factor_for_tof));
2269 new_erf = erf(temp/tof_sigma_sqrt2);
2270 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
2280 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
2299 int16_t index_x, index_z;
2300 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
2302 index_z = index[ 2 ] + jj * incr_orient_axial;
2303 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
2305 for( int16_t ii = 0; ii < n_distance_x - 1; ++ii )
2307 index_x = index[ 0 ] + ii * incr_orient_trans;
2308 if( index_x < 0 || index_x >
mp_nbVox[ 0 ] - 1 )
continue;
2310 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, index_x + j *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_x[ ii ], tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
2315 delete[] tof_weights_temp;
bool m_compatibleWithSPECTAttenuationCorrection
#define SPEED_OF_LIGHT_IN_MM_PER_PS
FLTNB m_TOFGaussianNormCoef
iProjectorDistanceDriven()
The constructor of iProjectorDistanceDriven.
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.
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
#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 ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project without TOF.
bool m_TOFWeightingFcnPrecomputedFlag
bool m_TOFBinProperProcessingFlag
HPFLTNB * mp_TOFWeightingFcn
FLTNB GetLength()
This function is used to get the length of the line.
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
int GetIndex2()
This function is used to get the index associated to point 2.
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...
~iProjectorDistanceDriven()
The destructor of iProjectorDistanceDriven.
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
FLTNB m_TOFResolutionInMm
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
INTNB GetNbVoxXY()
Get the number of voxels in a slice.
Declaration of class iProjectorDistanceDriven.
This class is designed to manage and store system matrix elements associated to a vEvent...
FLTNB m_TOFPrecomputedSamplingFactor
int ProjectTOFHistogram(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
Declaration of class sOutputManager.
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).
bool m_compatibleWithCompression
int GetIndex1()
This function is used to get the index associated to point 1.
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 ProjectTOFListmode(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
void ShowHelpSpecific()
A function used to show help about the child projector.
INTNB m_TOFWeightingFcnNbSamples
virtual int GetEdgesCenterPositions(int a_index1, int a_index2, FLTNB ap_pos_line_point1[3], FLTNB ap_pos_line_point2[3], FLTNB ap_pos_point1_x[4], FLTNB ap_pos_point1_y[4], FLTNB ap_pos_point1_z[4], FLTNB ap_pos_point2_x[4], FLTNB ap_pos_point2_y[4], FLTNB ap_pos_point2_z[4])=0
This is a pure virtual method that must be implemented by children. Get the cartesian coordinaters ...