106 cout <<
"This projector is a line projector based on computations of overlap between a pair of detection elements and voxels." << endl;
107 cout <<
"It is implemented from the following published paper:" << endl;
108 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;
132 if (
m_verbose>=2)
Cout(
"iProjectorDistanceDriven::InitializeSpecific() -> Use Distance Driven projector" << endl);
135 HPFLTNB tolerance_factor = 1.e-4;
165 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> Called while not initialized !" << endl);
170 #ifdef CASTOR_VERBOSE
173 string direction =
"";
174 if (a_direction==
FORWARD) direction =
"forward";
175 else direction =
"backward";
176 Cout(
"iProjectorDistanceDriven::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
234 &p1_x[1], &p1_y[1], &p1_z[1],
235 &p2_x[1], &p2_y[1], &p2_z[1]
238 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> A problem occured while getting the edges' center positions !" << endl);
249 p1_x[ 0 ] = p1[ 0 ]; p1_y[ 0 ] = p1[ 1 ]; p1_z[ 0 ] = p1[ 2 ];
252 p2_x[ 0 ] = p2[ 0 ]; p2_y[ 0 ] = p2[ 1 ]; p2_z[ 0 ] = p2[ 2 ];
261 for(
int p = 0; p < 5; ++p )
263 r[ p ][ 0 ] = p2_x[ p ] - p1_x[ p ];
264 r[ p ][ 1 ] = p2_y[ p ] - p1_y[ p ];
265 r[ p ][ 2 ] = p2_z[ p ] - p1_z[ p ];
270 r[ 0 ][ 0 ] * r[ 0 ][ 0 ],
271 r[ 0 ][ 1 ] * r[ 0 ][ 1 ],
272 r[ 0 ][ 2 ] * r[ 0 ][ 2 ]
277 HPFLTNB alpha_min = 0.0, alpha_max = 1.0;
281 HPFLTNB alpha_x_min[ 4 ], alpha_x_max[ 4 ];
282 HPFLTNB alpha_y_min[ 4 ], alpha_y_max[ 4 ];
283 HPFLTNB alpha_z_min[ 4 ], alpha_z_max[ 4 ];
308 float const angle = std::acos( ( r[ 0 ][ 0 ] ) / ( std::sqrt( r2[ 0 ] + r2[ 1 ] ) ) ) * 180.0f / M_PI;
311 if( ( angle >= 0.0 && angle <= 45.0 ) || ( angle >= 135.0 && angle <= 180.0 ) )
315 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
316 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
317 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
318 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
319 alpha_min = std::max( alpha_min, std::min( alpha_x_min[ 0 ], alpha_x_min[ 1 ] ) );
320 alpha_max = std::min( alpha_max, std::max( alpha_x_max[ 0 ], alpha_x_max[ 1 ] ) );
324 if( r[ 1 ][ 1 ] != 0.0 )
326 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
327 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
328 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
329 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
333 alpha_y_min[ 0 ] = 0.0;
334 alpha_y_min[ 1 ] = 0.0;
335 alpha_y_max[ 0 ] = 1.0;
336 alpha_y_max[ 1 ] = 1.0;
339 if( r[ 2 ][ 1 ] != 0.0 )
341 alpha_y_min[ 2 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
342 alpha_y_min[ 3 ] = (
mp_halfFOV[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
343 alpha_y_max[ 2 ] = alpha_y_min[ 2 ];
344 alpha_y_max[ 3 ] = alpha_y_min[ 3 ];
348 alpha_y_min[ 2 ] = 0.0;
349 alpha_y_min[ 3 ] = 0.0;
350 alpha_y_max[ 2 ] = 1.0;
351 alpha_y_max[ 3 ] = 1.0;
355 alpha_min = std::max( alpha_min,
356 alpha_y_min[ std::minmax_element( alpha_y_min, alpha_y_min + 4 ).first - alpha_y_min ] );
358 alpha_max = std::min( alpha_max,
359 alpha_y_max[ std::minmax_element( alpha_y_max, alpha_y_max + 4 ).second - alpha_y_max ] );
362 if( r[ 3 ][ 2 ] != 0.0 )
364 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
365 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
366 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
367 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
371 alpha_z_min[ 0 ] = 0.0;
372 alpha_z_min[ 1 ] = 0.0;
373 alpha_z_max[ 0 ] = 1.0;
374 alpha_z_max[ 1 ] = 1.0;
377 if( r[ 4 ][ 2 ] != 0.0 )
379 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
380 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
381 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
382 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
386 alpha_z_min[ 2 ] = 0.0;
387 alpha_z_min[ 3 ] = 0.0;
388 alpha_z_max[ 2 ] = 1.0;
389 alpha_z_max[ 3 ] = 1.0;
393 alpha_min = std::max( alpha_min,
394 alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first
397 alpha_max = std::min( alpha_max,
398 alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second
401 if( alpha_max <= alpha_min )
return 0;
404 int16_t i_min = 0, i_max = 0;
405 if( r[ 0 ][ 0 ] > 0.0 )
410 else if( r[ 0 ][ 0 ] < 0.0 )
418 HPFLTNB const factor( ::fabs( r[ 0 ][ 0 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
423 for( uint8_t p = 0; p < 4; ++p )
426 ri[ p ][ 1 ] = r[ p + 1 ][ 1 ] / r[ p + 1 ][ 0 ];
427 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 0 ];
431 int8_t incr_orient_trans = 0;
432 int8_t idx_orient_trans = 0;
435 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
439 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
445 for( int16_t i = i_min; i < i_max; ++i )
450 pos[ 0 ] = p1_y[ 1 ] + step * ri[ 0 ][ 1 ];
451 pos[ 1 ] = p1_y[ 2 ] + step * ri[ 1 ][ 1 ];
453 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
454 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
457 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
458 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
460 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
473 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
477 if( index[ 0 ] < index[ 1 ] )
479 incr_orient_trans = 1;
480 idx_orient_trans = 1;
482 else if( index[ 0 ] > index[ 1 ] )
484 incr_orient_trans = -1;
485 idx_orient_trans = 0;
489 int16_t
const n_distance_y = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
491 distance_y[ 0 ] = pos[ 0 ];
492 distance_y[ n_distance_y - 1 ] = pos[ 1 ];
494 if( n_distance_y > 2 )
496 for( int16_t d = 0; d < n_distance_y - 2; ++d )
497 distance_y[ d + 1 ] = (-
mp_halfFOV[ 1 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 1 ];
501 for( int16_t d = 0; d < n_distance_y - 1; ++d )
502 distance_y[ d ] = ::fabs( distance_y[ d + 1 ] - distance_y[ d ] );
505 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
507 distance_z[ 0 ] = pos[ 2 ];
508 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
510 if( n_distance_z > 2 )
512 for( int16_t d = 0; d < n_distance_z - 2; ++d )
513 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
517 for( int16_t d = 0; d < n_distance_z - 1; ++d )
518 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
521 int16_t index_y, index_z;
522 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
524 index_z = index[ 2 ] + jj * incr_orient_axial;
525 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
527 for( int16_t ii = 0; ii < n_distance_y - 1; ++ii )
529 index_y = index[ 0 ] + ii * incr_orient_trans;
530 if( index_y < 0 || index_y >
mp_nbVox[ 1 ] - 1 )
continue;
532 ap_ProjectionLine->
AddVoxel(a_direction, i + index_y *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_y[ ii ]);
541 if( r[ 1 ][ 0 ] != 0.0 )
543 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
544 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
545 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
546 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
550 alpha_x_min[ 0 ] = 0.0;
551 alpha_x_min[ 1 ] = 0.0;
552 alpha_x_max[ 0 ] = 1.0;
553 alpha_x_max[ 1 ] = 1.0;
556 if( r[ 2 ][ 0 ] != 0.0 )
558 alpha_x_min[ 2 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
559 alpha_x_min[ 3 ] = (
mp_halfFOV[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
560 alpha_x_max[ 2 ] = alpha_x_min[ 2 ];
561 alpha_x_max[ 3 ] = alpha_x_min[ 3 ];
565 alpha_x_min[ 2 ] = 0.0;
566 alpha_x_min[ 3 ] = 0.0;
567 alpha_x_max[ 2 ] = 1.0;
568 alpha_x_max[ 3 ] = 1.0;
572 alpha_min = std::max( alpha_min,
573 alpha_x_min[ std::minmax_element( alpha_x_min, alpha_x_min + 4 ).first - alpha_x_min ] );
575 alpha_max = std::min( alpha_max,
576 alpha_x_max[ std::minmax_element( alpha_x_max, alpha_x_max + 4 ).second - alpha_x_max ] );
580 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
581 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
582 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
583 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
584 alpha_min = std::max( alpha_min,
585 std::min( alpha_y_min[ 0 ], alpha_y_min[ 1 ] ) );
586 alpha_max = std::min( alpha_max,
587 std::max( alpha_y_max[ 0 ], alpha_y_max[ 1 ] ) );
590 if( r[ 3 ][ 2 ] != 0.0 )
592 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
593 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
594 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
595 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
599 alpha_z_min[ 0 ] = 0.0;
600 alpha_z_min[ 1 ] = 0.0;
601 alpha_z_max[ 0 ] = 1.0;
602 alpha_z_max[ 1 ] = 1.0;
605 if( r[ 4 ][ 2 ] != 0.0 )
607 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
608 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
609 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
610 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
614 alpha_z_min[ 2 ] = 0.0;
615 alpha_z_min[ 3 ] = 0.0;
616 alpha_z_max[ 2 ] = 1.0;
617 alpha_z_max[ 3 ] = 1.0;
621 alpha_min = std::max( alpha_min, alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first - alpha_z_min ] );
623 alpha_max = std::min( alpha_max, alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second - alpha_z_max ] );
625 if( alpha_max <= alpha_min )
return 0;
628 int16_t j_min = 0, j_max = 0;
629 if( r[ 0 ][ 1 ] > 0.0 )
634 else if( r[ 0 ][ 1 ] < 0.0 )
642 HPFLTNB const factor( ::fabs( r[ 0 ][ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
647 for( uint8_t p = 0; p < 4; ++p )
649 ri[ p ][ 0 ] = r[ p + 1 ][ 0 ] / r[ p + 1 ][ 1 ];
651 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 1 ];
655 int8_t incr_orient_trans = 0;
656 int8_t idx_orient_trans = 0;
659 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
661 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
667 for( int16_t j = j_min; j < j_max; ++j )
672 pos[ 0 ] = p1_x[ 1 ] + step * ri[ 0 ][ 0 ];
673 pos[ 1 ] = p1_x[ 2 ] + step * ri[ 1 ][ 0 ];
675 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
676 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
679 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
680 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
682 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
695 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
699 if( index[ 0 ] < index[ 1 ] )
701 incr_orient_trans = 1;
702 idx_orient_trans = 1;
704 else if( index[ 0 ] > index[ 1 ] )
706 incr_orient_trans = -1;
707 idx_orient_trans = 0;
711 int16_t
const n_distance_x = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
713 distance_x[ 0 ] = pos[ 0 ];
714 distance_x[ n_distance_x - 1 ] = pos[ 1 ];
716 if( n_distance_x > 2 )
718 for( int16_t d = 0; d < n_distance_x - 2; ++d )
719 distance_x[ d + 1 ] = (-
mp_halfFOV[ 0 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 0 ];
723 for( int16_t d = 0; d < n_distance_x - 1; ++d )
724 distance_x[ d ] = ::fabs( distance_x[ d + 1 ] - distance_x[ d ] );
727 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
729 distance_z[ 0 ] = pos[ 2 ];
730 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
732 if( n_distance_z > 2 )
734 for( int16_t d = 0; d < n_distance_z - 2; ++d )
735 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
739 for( int16_t d = 0; d < n_distance_z - 1; ++d )
740 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
743 int16_t index_x, index_z;
744 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
746 index_z = index[ 2 ] + jj * incr_orient_axial;
747 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
749 for( int16_t ii = 0; ii < n_distance_x - 1; ++ii )
751 index_x = index[ 0 ] + ii * incr_orient_trans;
752 if( index_x < 0 || index_x >
mp_nbVox[ 0 ] - 1 )
continue;
754 ap_ProjectionLine->
AddVoxel(a_direction, index_x + j *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_x[ ii ]);
773 Cerr(
"***** iProjectorDistanceDriven::ProjectWithTOFPos() -> Called while not initialized !" << endl);
778 #ifdef CASTOR_VERBOSE
781 string direction =
"";
782 if (a_direction==
FORWARD) direction =
"forward";
783 else direction =
"backward";
784 Cout(
"iProjectorDistanceDriven::Project with TOF measurement -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
841 &p1_x[1], &p1_y[1], &p1_z[1],
842 &p2_x[1], &p2_y[1], &p2_z[1]
845 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> A problem occured while getting the edges' center positions !" << endl);
856 p1_x[ 0 ] = p1[ 0 ]; p1_y[ 0 ] = p1[ 1 ]; p1_z[ 0 ] = p1[ 2 ];
859 p2_x[ 0 ] = p2[ 0 ]; p2_y[ 0 ] = p2[ 1 ]; p2_z[ 0 ] = p2[ 2 ];
868 for(
int p = 0; p < 5; ++p )
870 r[ p ][ 0 ] = p2_x[ p ] - p1_x[ p ];
871 r[ p ][ 1 ] = p2_y[ p ] - p1_y[ p ];
872 r[ p ][ 2 ] = p2_z[ p ] - p1_z[ p ];
877 r[ 0 ][ 0 ] * r[ 0 ][ 0 ],
878 r[ 0 ][ 1 ] * r[ 0 ][ 1 ],
879 r[ 0 ][ 2 ] * r[ 0 ][ 2 ]
884 HPFLTNB alpha_min = 0.0, alpha_max = 1.0;
888 HPFLTNB alpha_x_min[ 4 ], alpha_x_max[ 4 ];
889 HPFLTNB alpha_y_min[ 4 ], alpha_y_max[ 4 ];
890 HPFLTNB alpha_z_min[ 4 ], alpha_z_max[ 4 ];
931 HPFLTNB lor_tof_center = length_LOR * 0.5 + tof_delta;
934 HPFLTNB tof_edge_low[] = {0,0,0};
936 HPFLTNB tof_edge_high[] = {0,0,0};
937 HPFLTNB tof_center[] = {0,0,0};
941 for (
int ax=0;ax<3;ax++)
944 tof_center[ax] = p1[ax] + lor_tof_center * r[0][ax] / length_LOR;
947 tof_edge_low[ax] = tof_center[ax] - tof_half_span * fabs(r[0][ax]) / length_LOR;
950 if (tof_index>
mp_nbVox[ax]-1)
return 0;
954 tof_edge_high[ax] = tof_center[ax] + tof_half_span * fabs(r[0][ax]) / length_LOR;
957 if (tof_index<0)
return 0;
962 float const angle = std::acos( ( r[ 0 ][ 0 ] ) / ( std::sqrt( r2[ 0 ] + r2[ 1 ] ) ) ) * 180.0f / M_PI;
965 if( ( angle >= 0.0 && angle <= 45.0 ) || ( angle >= 135.0 && angle <= 180.0 ) )
970 alpha_x_min[ 0 ] = ( tof_edge_low[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
971 alpha_x_min[ 1 ] = ( tof_edge_high[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
972 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
973 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
974 alpha_min = std::max( alpha_min, std::min( alpha_x_min[ 0 ], alpha_x_min[ 1 ] ) );
975 alpha_max = std::min( alpha_max, std::max( alpha_x_max[ 0 ], alpha_x_max[ 1 ] ) );
979 if( r[ 1 ][ 1 ] != 0 )
981 alpha_y_min[ 0 ] = ( tof_edge_low[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
982 alpha_y_min[ 1 ] = ( tof_edge_high[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
983 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
984 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
988 alpha_y_min[ 0 ] = 0.0;
989 alpha_y_min[ 1 ] = 0.0;
990 alpha_y_max[ 0 ] = 1.0;
991 alpha_y_max[ 1 ] = 1.0;
994 if( r[ 2 ][ 1 ] != 0 )
996 alpha_y_min[ 2 ] = ( tof_edge_low[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
997 alpha_y_min[ 3 ] = ( tof_edge_high[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
998 alpha_y_max[ 2 ] = alpha_y_min[ 2 ];
999 alpha_y_max[ 3 ] = alpha_y_min[ 3 ];
1003 alpha_y_min[ 2 ] = 0.0;
1004 alpha_y_min[ 3 ] = 0.0;
1005 alpha_y_max[ 2 ] = 1.0;
1006 alpha_y_max[ 3 ] = 1.0;
1010 alpha_min = std::max( alpha_min,
1011 alpha_y_min[ std::minmax_element( alpha_y_min, alpha_y_min + 4 ).first - alpha_y_min ] );
1013 alpha_max = std::min( alpha_max,
1014 alpha_y_max[ std::minmax_element( alpha_y_max, alpha_y_max + 4 ).second - alpha_y_max ] );
1017 if( r[ 3 ][ 2 ] != 0 )
1019 alpha_z_min[ 0 ] = ( tof_edge_low[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1020 alpha_z_min[ 1 ] = ( tof_edge_high[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1021 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1022 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1026 alpha_z_min[ 0 ] = 0.0;
1027 alpha_z_min[ 1 ] = 0.0;
1028 alpha_z_max[ 0 ] = 1.0;
1029 alpha_z_max[ 1 ] = 1.0;
1032 if( r[ 4 ][ 2 ] != 0 )
1034 alpha_z_min[ 2 ] = ( tof_edge_low[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1035 alpha_z_min[ 3 ] = ( tof_edge_high[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1036 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1037 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1041 alpha_z_min[ 2 ] = 0.0;
1042 alpha_z_min[ 3 ] = 0.0;
1043 alpha_z_max[ 2 ] = 1.0;
1044 alpha_z_max[ 3 ] = 1.0;
1048 alpha_min = std::max( alpha_min,
1049 alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first
1052 alpha_max = std::min( alpha_max,
1053 alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second
1056 if( alpha_max <= alpha_min )
return 0;
1059 int16_t i_min = 0, i_max = 0;
1060 if( r[ 0 ][ 0 ] > 0.0 )
1065 else if( r[ 0 ][ 0 ] < 0.0 )
1073 HPFLTNB const factor( ::fabs( r[ 0 ][ 0 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
1076 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 0 ] );
1080 for( uint8_t p = 0; p < 4; ++p )
1083 ri[ p ][ 1 ] = r[ p + 1 ][ 1 ] / r[ p + 1 ][ 0 ];
1084 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 0 ];
1088 int8_t incr_orient_trans = 0;
1089 int8_t idx_orient_trans = 0;
1092 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
1096 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
1102 for( int16_t i = i_min; i < i_max; ++i )
1107 pos[ 0 ] = p1_y[ 1 ] + step * ri[ 0 ][ 1 ];
1108 pos[ 1 ] = p1_y[ 2 ] + step * ri[ 1 ][ 1 ];
1110 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
1111 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
1114 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
1115 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
1117 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
1130 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
1134 if( index[ 0 ] < index[ 1 ] )
1136 incr_orient_trans = 1;
1137 idx_orient_trans = 1;
1139 else if( index[ 0 ] > index[ 1 ] )
1141 incr_orient_trans = -1;
1142 idx_orient_trans = 0;
1146 int16_t
const n_distance_y = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
1148 distance_y[ 0 ] = pos[ 0 ];
1149 distance_y[ n_distance_y - 1 ] = pos[ 1 ];
1151 if( n_distance_y > 2 )
1153 for( int16_t d = 0; d < n_distance_y - 2; ++d )
1154 distance_y[ d + 1 ] = (-
mp_halfFOV[ 1 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 1 ];
1158 for( int16_t d = 0; d < n_distance_y - 1; ++d )
1159 distance_y[ d ] = ::fabs( distance_y[ d + 1 ] - distance_y[ d ] );
1162 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
1164 distance_z[ 0 ] = pos[ 2 ];
1165 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
1167 if( n_distance_z > 2 )
1169 for( int16_t d = 0; d < n_distance_z - 2; ++d )
1170 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
1174 for( int16_t d = 0; d < n_distance_z - 1; ++d )
1175 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
1178 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
1179 HPFLTNB tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef;
1182 int16_t index_y, index_z;
1183 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
1185 index_z = index[ 2 ] + jj * incr_orient_axial;
1186 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
1188 for( int16_t ii = 0; ii < n_distance_y - 1; ++ii )
1190 index_y = index[ 0 ] + ii * incr_orient_trans;
1191 if( index_y < 0 || index_y >
mp_nbVox[ 1 ] - 1 )
continue;
1193 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, i + index_y *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_y[ ii ] * tof_weight);
1203 if( r[ 1 ][ 0 ] != 0.0 )
1205 alpha_x_min[ 0 ] = ( tof_edge_low[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
1206 alpha_x_min[ 1 ] = ( tof_edge_high[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
1207 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
1208 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
1212 alpha_x_min[ 0 ] = 0.0;
1213 alpha_x_min[ 1 ] = 0.0;
1214 alpha_x_max[ 0 ] = 1.0;
1215 alpha_x_max[ 1 ] = 1.0;
1218 if( r[ 2 ][ 0 ] != 0 )
1220 alpha_x_min[ 2 ] = ( tof_edge_low[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
1221 alpha_x_min[ 3 ] = ( tof_edge_high[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
1222 alpha_x_max[ 2 ] = alpha_x_min[ 2 ];
1223 alpha_x_max[ 3 ] = alpha_x_min[ 3 ];
1227 alpha_x_min[ 2 ] = 0.0;
1228 alpha_x_min[ 3 ] = 0.0;
1229 alpha_x_max[ 2 ] = 1.0;
1230 alpha_x_max[ 3 ] = 1.0;
1234 alpha_min = std::max( alpha_min,
1235 alpha_x_min[ std::minmax_element( alpha_x_min, alpha_x_min + 4 ).first - alpha_x_min ] );
1237 alpha_max = std::min( alpha_max,
1238 alpha_x_max[ std::minmax_element( alpha_x_max, alpha_x_max + 4 ).second - alpha_x_max ] );
1242 alpha_y_min[ 0 ] = ( tof_edge_low[1] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
1243 alpha_y_min[ 1 ] = ( tof_edge_high[1] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
1244 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
1245 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
1246 alpha_min = std::max( alpha_min,
1247 std::min( alpha_y_min[ 0 ], alpha_y_min[ 1 ] ) );
1248 alpha_max = std::min( alpha_max,
1249 std::max( alpha_y_max[ 0 ], alpha_y_max[ 1 ] ) );
1252 if( r[ 3 ][ 2 ] != 0 )
1254 alpha_z_min[ 0 ] = ( tof_edge_low[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1255 alpha_z_min[ 1 ] = ( tof_edge_high[ 2 ]- p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1256 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1257 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1261 alpha_z_min[ 0 ] = 0.0;
1262 alpha_z_min[ 1 ] = 0.0;
1263 alpha_z_max[ 0 ] = 1.0;
1264 alpha_z_max[ 1 ] = 1.0;
1267 if( r[ 4 ][ 2 ] != 0 )
1269 alpha_z_min[ 2 ] = ( tof_edge_low[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1270 alpha_z_min[ 3 ] = ( tof_edge_high[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1271 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1272 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1276 alpha_z_min[ 2 ] = 0.0;
1277 alpha_z_min[ 3 ] = 0.0;
1278 alpha_z_max[ 2 ] = 1.0;
1279 alpha_z_max[ 3 ] = 1.0;
1283 alpha_min = std::max( alpha_min, alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first - alpha_z_min ] );
1285 alpha_max = std::min( alpha_max, alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second - alpha_z_max ] );
1287 if( alpha_max <= alpha_min )
return 0;
1290 int16_t j_min = 0, j_max = 0;
1291 if( r[ 0 ][ 1 ] > 0.0 )
1296 else if( r[ 0 ][ 1 ] < 0.0 )
1304 HPFLTNB const factor( ::fabs( r[ 0 ][ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
1306 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 1 ] );
1310 for( uint8_t p = 0; p < 4; ++p )
1312 ri[ p ][ 0 ] = r[ p + 1 ][ 0 ] / r[ p + 1 ][ 1 ];
1314 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 1 ];
1318 int8_t incr_orient_trans = 0;
1319 int8_t idx_orient_trans = 0;
1322 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
1324 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
1330 for( int16_t j = j_min; j < j_max; ++j )
1335 pos[ 0 ] = p1_x[ 1 ] + step * ri[ 0 ][ 0 ];
1336 pos[ 1 ] = p1_x[ 2 ] + step * ri[ 1 ][ 0 ];
1338 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
1339 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
1342 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
1343 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
1345 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
1358 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
1362 if( index[ 0 ] < index[ 1 ] )
1364 incr_orient_trans = 1;
1365 idx_orient_trans = 1;
1367 else if( index[ 0 ] > index[ 1 ] )
1369 incr_orient_trans = -1;
1370 idx_orient_trans = 0;
1374 int16_t
const n_distance_x = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
1376 distance_x[ 0 ] = pos[ 0 ];
1377 distance_x[ n_distance_x - 1 ] = pos[ 1 ];
1379 if( n_distance_x > 2 )
1381 for( int16_t d = 0; d < n_distance_x - 2; ++d )
1382 distance_x[ d + 1 ] = (-
mp_halfFOV[ 0 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 0 ];
1386 for( int16_t d = 0; d < n_distance_x - 1; ++d )
1387 distance_x[ d ] = ::fabs( distance_x[ d + 1 ] - distance_x[ d ] );
1390 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
1392 distance_z[ 0 ] = pos[ 2 ];
1393 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
1395 if( n_distance_z > 2 )
1397 for( int16_t d = 0; d < n_distance_z - 2; ++d )
1398 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
1402 for( int16_t d = 0; d < n_distance_z - 1; ++d )
1403 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
1406 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
1407 HPFLTNB tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef;
1410 int16_t index_x, index_z;
1411 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
1413 index_z = index[ 2 ] + jj * incr_orient_axial;
1414 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
1416 for( int16_t ii = 0; ii < n_distance_x - 1; ++ii )
1418 index_x = index[ 0 ] + ii * incr_orient_trans;
1419 if( index_x < 0 || index_x >
mp_nbVox[ 0 ] - 1 )
continue;
1421 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, index_x + j *
mp_nbVox[ 0 ] + index_z * m_nbVoxXY, final_weight * distance_z[ jj ] * distance_x[ ii ] * tof_weight);
1440 Cerr(
"***** iProjectorDistanceDriven::ProjectWithTOFBin() -> Called while not initialized !" << endl);
1445 #ifdef CASTOR_VERBOSE
1448 string direction =
"";
1449 if (a_direction==
FORWARD) direction =
"forward";
1450 else direction =
"backward";
1451 Cout(
"iProjectorDistanceDriven::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
1502 INTNB tof_half_nb_bins = tof_nb_bins/2;
1516 INTNB tof_bin_last = tof_half_nb_bins;
1517 INTNB tof_bin_first = -tof_half_nb_bins;
1531 HPFLTNB length_LOR_half = length_LOR * 0.5;
1533 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
1549 &p1_x[1], &p1_y[1], &p1_z[1],
1550 &p2_x[1], &p2_y[1], &p2_z[1]
1553 Cerr(
"***** iProjectorDistanceDriven::ProjectWithoutTOF() -> A problem occured while getting the edges' center positions !" << endl);
1564 p1_x[ 0 ] = p1[ 0 ]; p1_y[ 0 ] = p1[ 1 ]; p1_z[ 0 ] = p1[ 2 ];
1567 p2_x[ 0 ] = p2[ 0 ]; p2_y[ 0 ] = p2[ 1 ]; p2_z[ 0 ] = p2[ 2 ];
1576 for(
int p = 0; p < 5; ++p )
1578 r[ p ][ 0 ] = p2_x[ p ] - p1_x[ p ];
1579 r[ p ][ 1 ] = p2_y[ p ] - p1_y[ p ];
1580 r[ p ][ 2 ] = p2_z[ p ] - p1_z[ p ];
1585 r[ 0 ][ 0 ] * r[ 0 ][ 0 ],
1586 r[ 0 ][ 1 ] * r[ 0 ][ 1 ],
1587 r[ 0 ][ 2 ] * r[ 0 ][ 2 ]
1592 HPFLTNB alpha_min = 0.0, alpha_max = 1.0;
1596 HPFLTNB alpha_x_min[ 4 ], alpha_x_max[ 4 ];
1597 HPFLTNB alpha_y_min[ 4 ], alpha_y_max[ 4 ];
1598 HPFLTNB alpha_z_min[ 4 ], alpha_z_max[ 4 ];
1623 float const angle = std::acos( ( r[ 0 ][ 0 ] ) / ( std::sqrt( r2[ 0 ] + r2[ 1 ] ) ) ) * 180.0f / M_PI;
1626 if( ( angle >= 0.0 && angle <= 45.0 ) || ( angle >= 135.0 && angle <= 180.0 ) )
1630 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
1631 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 0 ] ) / r[ 0 ][ 0 ];
1632 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
1633 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
1634 alpha_min = std::max( alpha_min, std::min( alpha_x_min[ 0 ], alpha_x_min[ 1 ] ) );
1635 alpha_max = std::min( alpha_max, std::max( alpha_x_max[ 0 ], alpha_x_max[ 1 ] ) );
1639 if( r[ 1 ][ 1 ] != 0.0 )
1641 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
1642 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 1 ] ) / r[ 1 ][ 1 ];
1643 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
1644 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
1648 alpha_y_min[ 0 ] = 0.0;
1649 alpha_y_min[ 1 ] = 0.0;
1650 alpha_y_max[ 0 ] = 1.0;
1651 alpha_y_max[ 1 ] = 1.0;
1654 if( r[ 2 ][ 1 ] != 0.0 )
1656 alpha_y_min[ 2 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
1657 alpha_y_min[ 3 ] = (
mp_halfFOV[ 1 ] - p1_y[ 2 ] ) / r[ 2 ][ 1 ];
1658 alpha_y_max[ 2 ] = alpha_y_min[ 2 ];
1659 alpha_y_max[ 3 ] = alpha_y_min[ 3 ];
1663 alpha_y_min[ 2 ] = 0.0;
1664 alpha_y_min[ 3 ] = 0.0;
1665 alpha_y_max[ 2 ] = 1.0;
1666 alpha_y_max[ 3 ] = 1.0;
1670 alpha_min = std::max( alpha_min,
1671 alpha_y_min[ std::minmax_element( alpha_y_min, alpha_y_min + 4 ).first - alpha_y_min ] );
1673 alpha_max = std::min( alpha_max,
1674 alpha_y_max[ std::minmax_element( alpha_y_max, alpha_y_max + 4 ).second - alpha_y_max ] );
1677 if( r[ 3 ][ 2 ] != 0.0 )
1679 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1680 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1681 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1682 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1686 alpha_z_min[ 0 ] = 0.0;
1687 alpha_z_min[ 1 ] = 0.0;
1688 alpha_z_max[ 0 ] = 1.0;
1689 alpha_z_max[ 1 ] = 1.0;
1692 if( r[ 4 ][ 2 ] != 0.0 )
1694 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1695 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1696 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1697 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1701 alpha_z_min[ 2 ] = 0.0;
1702 alpha_z_min[ 3 ] = 0.0;
1703 alpha_z_max[ 2 ] = 1.0;
1704 alpha_z_max[ 3 ] = 1.0;
1708 alpha_min = std::max( alpha_min,
1709 alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first
1712 alpha_max = std::min( alpha_max,
1713 alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second
1716 if( alpha_max <= alpha_min )
return 0;
1721 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1724 int16_t i_min = 0, i_max = 0;
1725 if( r[ 0 ][ 0 ] > 0.0 )
1730 else if( r[ 0 ][ 0 ] < 0.0 )
1738 HPFLTNB const factor( ::fabs( r[ 0 ][ 0 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
1739 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 0 ] );
1744 for( uint8_t p = 0; p < 4; ++p )
1747 ri[ p ][ 1 ] = r[ p + 1 ][ 1 ] / r[ p + 1 ][ 0 ];
1748 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 0 ];
1752 int8_t incr_orient_trans = 0;
1753 int8_t idx_orient_trans = 0;
1756 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
1760 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
1766 for( int16_t i = i_min; i < i_max; ++i )
1771 pos[ 0 ] = p1_y[ 1 ] + step * ri[ 0 ][ 1 ];
1772 pos[ 1 ] = p1_y[ 2 ] + step * ri[ 1 ][ 1 ];
1774 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
1775 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
1778 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
1779 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
1781 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
1794 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
1798 if( index[ 0 ] < index[ 1 ] )
1800 incr_orient_trans = 1;
1801 idx_orient_trans = 1;
1803 else if( index[ 0 ] > index[ 1 ] )
1805 incr_orient_trans = -1;
1806 idx_orient_trans = 0;
1810 int16_t
const n_distance_y = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
1812 distance_y[ 0 ] = pos[ 0 ];
1813 distance_y[ n_distance_y - 1 ] = pos[ 1 ];
1815 if( n_distance_y > 2 )
1817 for( int16_t d = 0; d < n_distance_y - 2; ++d )
1818 distance_y[ d + 1 ] = (-
mp_halfFOV[ 1 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 1 ];
1822 for( int16_t d = 0; d < n_distance_y - 1; ++d )
1823 distance_y[ d ] = ::fabs( distance_y[ d + 1 ] - distance_y[ d ] );
1826 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
1828 distance_z[ 0 ] = pos[ 2 ];
1829 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
1831 if( n_distance_z > 2 )
1833 for( int16_t d = 0; d < n_distance_z - 2; ++d )
1834 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
1838 for( int16_t d = 0; d < n_distance_z - 1; ++d )
1839 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
1842 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(trunc( (step * factor_for_tof - tof_half_span - length_LOR_half ) / tof_bin_size )));
1843 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(trunc( (step * factor_for_tof + tof_half_span - length_LOR_half) / tof_bin_size )));
1844 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel * tof_bin_size;
1847 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
1850 tof_bin_first_for_voxel += tof_half_nb_bins;
1851 tof_bin_last_for_voxel += tof_half_nb_bins;
1855 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1858 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
1859 tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef;
1861 tof_norm_coef += tof_weight;
1863 tof_weights_temp[tof_bin] = tof_weight;
1865 lor_tof_center += tof_bin_size;
1869 if (tof_norm_coef>0.)
1871 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1874 tof_weights_temp[tof_bin] /= tof_norm_coef;
1878 int16_t index_y, index_z;
1879 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
1881 index_z = index[ 2 ] + jj * incr_orient_axial;
1882 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
1884 for( int16_t ii = 0; ii < n_distance_y - 1; ++ii )
1886 index_y = index[ 0 ] + ii * incr_orient_trans;
1887 if( index_y < 0 || index_y >
mp_nbVox[ 1 ] - 1 )
continue;
1889 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);
1894 delete[] tof_weights_temp;
1900 if( r[ 1 ][ 0 ] != 0.0 )
1902 alpha_x_min[ 0 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
1903 alpha_x_min[ 1 ] = (
mp_halfFOV[ 0 ] - p1_x[ 1 ] ) / r[ 1 ][ 0 ];
1904 alpha_x_max[ 0 ] = alpha_x_min[ 0 ];
1905 alpha_x_max[ 1 ] = alpha_x_min[ 1 ];
1909 alpha_x_min[ 0 ] = 0.0;
1910 alpha_x_min[ 1 ] = 0.0;
1911 alpha_x_max[ 0 ] = 1.0;
1912 alpha_x_max[ 1 ] = 1.0;
1915 if( r[ 2 ][ 0 ] != 0.0 )
1917 alpha_x_min[ 2 ] = ( (-
mp_halfFOV[ 0 ]) - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
1918 alpha_x_min[ 3 ] = (
mp_halfFOV[ 0 ] - p1_x[ 2 ] ) / r[ 2 ][ 0 ];
1919 alpha_x_max[ 2 ] = alpha_x_min[ 2 ];
1920 alpha_x_max[ 3 ] = alpha_x_min[ 3 ];
1924 alpha_x_min[ 2 ] = 0.0;
1925 alpha_x_min[ 3 ] = 0.0;
1926 alpha_x_max[ 2 ] = 1.0;
1927 alpha_x_max[ 3 ] = 1.0;
1931 alpha_min = std::max( alpha_min,
1932 alpha_x_min[ std::minmax_element( alpha_x_min, alpha_x_min + 4 ).first - alpha_x_min ] );
1934 alpha_max = std::min( alpha_max,
1935 alpha_x_max[ std::minmax_element( alpha_x_max, alpha_x_max + 4 ).second - alpha_x_max ] );
1939 alpha_y_min[ 0 ] = ( (-
mp_halfFOV[ 1 ]) - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
1940 alpha_y_min[ 1 ] = (
mp_halfFOV[ 1 ] - p1_y[ 0 ] ) / r[ 0 ][ 1 ];
1941 alpha_y_max[ 0 ] = alpha_y_min[ 0 ];
1942 alpha_y_max[ 1 ] = alpha_y_min[ 1 ];
1943 alpha_min = std::max( alpha_min,
1944 std::min( alpha_y_min[ 0 ], alpha_y_min[ 1 ] ) );
1945 alpha_max = std::min( alpha_max,
1946 std::max( alpha_y_max[ 0 ], alpha_y_max[ 1 ] ) );
1949 if( r[ 3 ][ 2 ] != 0.0 )
1951 alpha_z_min[ 0 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1952 alpha_z_min[ 1 ] = (
mp_halfFOV[ 2 ] - p1_z[ 3 ] ) / r[ 3 ][ 2 ];
1953 alpha_z_max[ 0 ] = alpha_z_min[ 0 ];
1954 alpha_z_max[ 1 ] = alpha_z_min[ 1 ];
1958 alpha_z_min[ 0 ] = 0.0;
1959 alpha_z_min[ 1 ] = 0.0;
1960 alpha_z_max[ 0 ] = 1.0;
1961 alpha_z_max[ 1 ] = 1.0;
1964 if( r[ 4 ][ 2 ] != 0.0 )
1966 alpha_z_min[ 2 ] = ( (-
mp_halfFOV[ 2 ]) - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1967 alpha_z_min[ 3 ] = (
mp_halfFOV[ 2 ] - p1_z[ 4 ] ) / r[ 4 ][ 2 ];
1968 alpha_z_max[ 2 ] = alpha_z_min[ 2 ];
1969 alpha_z_max[ 3 ] = alpha_z_min[ 3 ];
1973 alpha_z_min[ 2 ] = 0.0;
1974 alpha_z_min[ 3 ] = 0.0;
1975 alpha_z_max[ 2 ] = 1.0;
1976 alpha_z_max[ 3 ] = 1.0;
1980 alpha_min = std::max( alpha_min, alpha_z_min[ std::minmax_element( alpha_z_min, alpha_z_min + 4 ).first - alpha_z_min ] );
1982 alpha_max = std::min( alpha_max, alpha_z_max[ std::minmax_element( alpha_z_max, alpha_z_max + 4 ).second - alpha_z_max ] );
1984 if( alpha_max <= alpha_min )
return 0;
1989 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1992 int16_t j_min = 0, j_max = 0;
1993 if( r[ 0 ][ 1 ] > 0.0 )
1998 else if( r[ 0 ][ 1 ] < 0.0 )
2006 HPFLTNB const factor( ::fabs( r[ 0 ][ 1 ] ) / ::sqrt( r2[ 0 ] + r2[ 1 ] + r2[ 2 ] ) );
2007 HPFLTNB const factor_for_tof( length_LOR / r[ 0 ][ 1 ] );
2012 for( uint8_t p = 0; p < 4; ++p )
2014 ri[ p ][ 0 ] = r[ p + 1 ][ 0 ] / r[ p + 1 ][ 1 ];
2016 ri[ p ][ 2 ] = r[ p + 1 ][ 2 ] / r[ p + 1 ][ 1 ];
2020 int8_t incr_orient_trans = 0;
2021 int8_t idx_orient_trans = 0;
2024 int8_t
const incr_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : -1;
2026 int8_t
const idx_orient_axial = p2_z[ 3 ] < p2_z[ 4 ] ? 1 : 0;
2032 for( int16_t j = j_min; j < j_max; ++j )
2037 pos[ 0 ] = p1_x[ 1 ] + step * ri[ 0 ][ 0 ];
2038 pos[ 1 ] = p1_x[ 2 ] + step * ri[ 1 ][ 0 ];
2040 pos[ 2 ] = p1_z[ 3 ] + step * ri[ 2 ][ 2 ];
2041 pos[ 3 ] = p1_z[ 4 ] + step * ri[ 3 ][ 2 ];
2044 w1 = ::fabs( pos[ 0 ] - pos[ 1 ] );
2045 w2 = ::fabs( pos[ 2 ] - pos[ 3 ] );
2047 if( ( w1 * w2 ) != 0 ) final_weight = weight / ( w1 * w2 );
2059 bool test_index = (index[ 0 ] >= 0 && index[ 2 ] >= 0 && index[ 1 ] >= 0 && index[ 3 ] >= 0
2063 if( index[ 0 ] < index[ 1 ] )
2065 incr_orient_trans = 1;
2066 idx_orient_trans = 1;
2068 else if( index[ 0 ] > index[ 1 ] )
2070 incr_orient_trans = -1;
2071 idx_orient_trans = 0;
2075 int16_t
const n_distance_x = ::abs( index[ 0 ] - index[ 1 ] ) + 2;
2077 distance_x[ 0 ] = pos[ 0 ];
2078 distance_x[ n_distance_x - 1 ] = pos[ 1 ];
2080 if( n_distance_x > 2 )
2082 for( int16_t d = 0; d < n_distance_x - 2; ++d )
2083 distance_x[ d + 1 ] = (-
mp_halfFOV[ 0 ]) + ( index[ 0 ] + idx_orient_trans + ( incr_orient_trans * d ) ) * mp_sizeVox[ 0 ];
2087 for( int16_t d = 0; d < n_distance_x - 1; ++d )
2088 distance_x[ d ] = ::fabs( distance_x[ d + 1 ] - distance_x[ d ] );
2091 int16_t
const n_distance_z = ::abs( index[ 2 ] - index[ 3 ] ) + 2;
2093 distance_z[ 0 ] = pos[ 2 ];
2094 distance_z[ n_distance_z - 1 ] = pos[ 3 ];
2096 if( n_distance_z > 2 )
2098 for( int16_t d = 0; d < n_distance_z - 2; ++d )
2099 distance_z[ d + 1 ] = (-
mp_halfFOV[ 2 ]) + ( index[ 2 ] + idx_orient_axial + ( incr_orient_axial * d ) ) * mp_sizeVox[ 2 ];
2103 for( int16_t d = 0; d < n_distance_z - 1; ++d )
2104 distance_z[ d ] = ::fabs( distance_z[ d + 1 ] - distance_z[ d ] );
2107 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(trunc( (step * factor_for_tof - tof_half_span - length_LOR_half ) / tof_bin_size )));
2108 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(trunc( (step * factor_for_tof + tof_half_span - length_LOR_half) / tof_bin_size )));
2109 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel * tof_bin_size;
2112 if(tof_bin_first_for_voxel>tof_bin_last || tof_bin_last_for_voxel<tof_bin_first)
continue;
2115 tof_bin_first_for_voxel += tof_half_nb_bins;
2116 tof_bin_last_for_voxel += tof_half_nb_bins;
2120 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
2123 HPFLTNB temp = (step * factor_for_tof - lor_tof_center) / tof_sigma;
2124 tof_weight = exp(- 0.5 * temp * temp ) * gaussian_norm_coef;
2126 tof_norm_coef += tof_weight;
2128 tof_weights_temp[tof_bin] = tof_weight;
2130 lor_tof_center += tof_bin_size;
2134 if (tof_norm_coef>0.)
2136 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
2139 tof_weights_temp[tof_bin] /= tof_norm_coef;
2143 int16_t index_x, index_z;
2144 for( int16_t jj = 0; jj < n_distance_z - 1; ++jj )
2146 index_z = index[ 2 ] + jj * incr_orient_axial;
2147 if( index_z < 0 || index_z >
mp_nbVox[ 2 ] - 1 )
continue;
2149 for( int16_t ii = 0; ii < n_distance_x - 1; ++ii )
2151 index_x = index[ 0 ] + ii * incr_orient_trans;
2152 if( index_x < 0 || index_x >
mp_nbVox[ 0 ] - 1 )
continue;
2154 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);
2159 delete[] tof_weights_temp;
bool m_compatibleWithSPECTAttenuationCorrection
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
This class is designed to generically described any on-the-fly projector.
FLTNB GetTOFMeasurement()
This function is used to get the TOF measurement.
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.
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.
FLTNB GetTOFResolution()
This function is used to get the TOF resolution.
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.
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
INTNB GetNbVoxXY()
Get the number of voxels in a slice.
int ProjectWithTOFPos(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
Declaration of class iProjectorDistanceDriven.
This class is designed to manage and store system matrix elements associated to a vEvent...
Declaration of class sOutputManager.
int GetNbTOFBins()
This function is used to get the number of TOF bins in use.
int ProjectWithTOFBin(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
FLTNB * GetPosition2()
This function is used to get the pointer to the mp_position2 (3-values tab).
FLTNB GetTOFBinSize()
This function is used to get the size in ps of a TOF bin.
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 GetIndex1()
This function is used to get the index associated to point 1.
void ShowHelpSpecific()
A function used to show help about the child projector.
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 ...