110 cout <<
"This projector is a line projector that uses linear interpolation between pixels." << endl;
111 cout <<
"It is implemented from the following published paper:" << endl;
112 cout <<
"P. M. Joseph, \"An improved algorithm for reprojecting rays through pixel images\", IEEE Trans. Med. Imaging, vol. 1, pp. 192-6, 1982." << endl;
136 if (
m_verbose>=2)
Cout(
"iProjectorJoseph::InitializeSpecific() -> Use Joseph projector" << endl);
147 INTNB nElts = ( mp_nbVox[ 0 ] + 2 ) * ( mp_nbVox[ 1 ] + 2 ) * ( mp_nbVox[ 2 ] + 2 );
149 ::memset(
mp_maskPad, 0,
sizeof( uint8_t ) * nElts );
150 for(
INTNB k = 1; k < mp_nbVox[ 2 ] + 1; ++k )
152 for(
INTNB j = 1; j < mp_nbVox[ 1 ] + 1; ++j )
154 for(
INTNB i = 1; i < mp_nbVox[ 0 ] + 1; ++i )
156 mp_maskPad[ i + j * ( ( mp_nbVox[ 0 ] + 2 ) ) + k * ( mp_nbVox[ 0 ] + 2 ) * ( mp_nbVox[ 1 ] + 2 ) ] = 1;
162 double tolerance_factor = 1.e-4;
183 max_nb_voxels_in_dimension *= 4;
185 return max_nb_voxels_in_dimension;
198 Cerr(
"***** iProjectorJoseph::ProjectWithoutTOF() -> Called while not initialized !" << endl);
203 #ifdef CASTOR_VERBOSE
206 string direction =
"";
207 if (a_direction==
FORWARD) direction =
"forward";
208 else direction =
"backward";
209 Cout(
"iProjectorJoseph::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
218 double const dX21( event2[ 0 ] - event1[ 0 ] );
219 double const dY21( event2[ 1 ] - event1[ 1 ] );
220 double const dZ21( event2[ 2 ] - event1[ 2 ] );
223 double const fabs_dX21 = ::fabs(dX21);
224 double const fabs_dY21 = ::fabs(dY21);
225 double const fabs_dZ21 = ::fabs(dZ21);
236 INTNB const nPlane_XY( nPlane_X * nPlane_Y );
239 INTNB const nPlane_X_Pad( nPlane_X + 2 );
240 INTNB const nPlane_Y_Pad( nPlane_Y + 2 );
241 INTNB const nPlane_XY_Pad( nPlane_X_Pad * nPlane_Y_Pad );
258 double intersection_x( event1[ 0 ] < xPlane_0 ?
259 xPlane_0 + szImg_X / 2.0 : xPlane_N - szImg_X / 2.0 );
262 double intersection_y( event1[ 1 ] < yPlane_0 ?
263 yPlane_0 + szImg_Y / 2.0 : yPlane_N - szImg_Y / 2.0 );
266 double intersection_z( event1[ 2 ] < zPlane_0 ?
267 zPlane_0 + szImg_Z / 2.0 : zPlane_N - szImg_Z / 2.0 );
270 double const xPlane_0_min = xPlane_0 + szImg_X / 2.0;
271 double const yPlane_0_min = yPlane_0 + szImg_Y / 2.0;
272 double const zPlane_0_min = zPlane_0 + szImg_Z / 2.0;
275 double const xPlane_0_min_safety = xPlane_0 - ( szImg_X / 2.0 );
276 double const yPlane_0_min_safety = yPlane_0 - ( szImg_Y / 2.0 );
277 double const zPlane_0_min_safety = zPlane_0 - ( szImg_Z / 2.0 );
278 double const xPlane_N_max_safety = xPlane_N + ( szImg_X / 2.0 );
279 double const yPlane_N_max_safety = yPlane_N + ( szImg_Y / 2.0 );
280 double const zPlane_N_max_safety = zPlane_N + ( szImg_Z / 2.0 );
283 double const increment[] = {
284 event1[ 0 ] < xPlane_0 ? szImg_X : -szImg_X,
285 event1[ 1 ] < yPlane_0 ? szImg_Y : -szImg_Y,
286 event1[ 2 ] < zPlane_0 ? szImg_Z : -szImg_Z
289 INTNB const increment_index[] = {
290 event1[ 0 ] < xPlane_0 ? 1 : -1,
291 event1[ 1 ] < yPlane_0 ? 1 : -1,
292 event1[ 2 ] < zPlane_0 ? 1 : -1
295 INTNB const first_index[] = {
296 event1[ 0 ] < xPlane_0 ? 0 : nPlane_X - 1,
297 event1[ 1 ] < yPlane_0 ? 0 : nPlane_Y - 1,
298 event1[ 2 ] < zPlane_0 ? 0 : nPlane_Z - 1
302 double x1( 0.0 );
double x2( 0.0 );
303 double y1( 0.0 );
double y2( 0.0 );
304 double z1( 0.0 );
double z2( 0.0 );
308 if( fabs_dX21 >= fabs_dY21 && fabs_dX21 >= fabs_dZ21 )
311 double const weight( ((
double)(ap_ProjectionLine->
GetLength())) * szImg_X / fabs_dX21 );
314 double const incrementX = increment[ 0 ];
317 double const p1X_IntersectionX1 = ( intersection_x - event1[ 0 ] );
318 intersection_y = ( p1X_IntersectionX1 * dY21 / dX21 ) + event1[ 1 ];
319 intersection_z = ( p1X_IntersectionX1 * dZ21 / dX21 ) + event1[ 2 ];
322 double const incrementY =
323 ( ( intersection_x + incrementX - event1[ 0 ] ) * dY21 / dX21 )
324 + event1[ 1 ] - intersection_y;
325 double const incrementZ =
326 ( ( intersection_x + incrementX - event1[ 0 ] ) * dZ21 / dX21 )
327 + event1[ 2 ] - intersection_z;
330 index_x = first_index[ 0 ];
333 for(
INTNB i = 0; i < nPlane_X; ++i )
336 if( intersection_y < ( yPlane_0_min_safety +
m_toleranceY )
337 || intersection_y >= ( yPlane_N_max_safety -
m_toleranceY )
338 || intersection_z < ( zPlane_0_min_safety +
m_toleranceZ )
339 || intersection_z >= ( zPlane_N_max_safety -
m_toleranceZ ) )
341 index_x += increment_index[ 0 ];
342 intersection_y += incrementY;
343 intersection_z += incrementZ;
348 index_y = ::floor( ( intersection_y - yPlane_0_min ) / szImg_Y );
349 index_z = ::floor( ( intersection_z - zPlane_0_min ) / szImg_Z );
352 y2 = ( intersection_y -
mp_boundariesY[ index_y + 1 ] ) / szImg_Y;
354 z2 = ( intersection_z -
mp_boundariesZ[ index_z + 1 ] ) / szImg_Z;
358 INTNB index_final = index_x + index_y * nPlane_X + index_z * nPlane_XY;
361 INTNB index_final_pad = ( index_x + 1 ) + ( index_y + 1 ) * nPlane_X_Pad + ( index_z + 1 ) * nPlane_XY_Pad;
365 INTNB maskIdx4 =
mp_maskPad[ index_final_pad + nPlane_X_Pad + nPlane_XY_Pad ];
367 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final ) * maskIdx1, ( y1 * z1 ) * weight * maskIdx1);
368 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + nPlane_X ) * maskIdx2, ( y2 * z1 ) * weight * maskIdx2);
369 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + nPlane_XY ) * maskIdx3, ( y1 * z2 ) * weight * maskIdx3);
370 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + nPlane_X + nPlane_XY ) * maskIdx4, ( y2 * z2 ) * weight * maskIdx4);
373 index_x += increment_index[ 0 ];
374 intersection_y += incrementY;
375 intersection_z += incrementZ;
378 else if( fabs_dY21 > fabs_dX21 && fabs_dY21 >= fabs_dZ21 )
381 double const weight( ((
double)(ap_ProjectionLine->
GetLength())) * szImg_Y / fabs_dY21 );
384 double const incrementY = increment[ 1 ];
387 double const p1Y_IntersectionY1 = ( intersection_y - event1[ 1 ] );
388 intersection_x = ( p1Y_IntersectionY1 * dX21 / dY21 ) + event1[ 0 ];
389 intersection_z = ( p1Y_IntersectionY1 * dZ21 / dY21 ) + event1[ 2 ];
392 double const incrementX =
393 ( ( intersection_y + incrementY - event1[ 1 ] ) * dX21 / dY21 )
394 + event1[ 0 ] - intersection_x;
395 double const incrementZ =
396 ( ( intersection_y + incrementY - event1[ 1 ] ) * dZ21 / dY21 )
397 + event1[ 2 ] - intersection_z;
400 index_y = first_index[ 1 ];
403 for(
INTNB i = 0; i < nPlane_Y; ++i )
406 if( intersection_x < ( xPlane_0_min_safety +
m_toleranceX )
407 || intersection_x >= ( xPlane_N_max_safety -
m_toleranceX )
408 || intersection_z < ( zPlane_0_min_safety +
m_toleranceZ )
409 || intersection_z >= ( zPlane_N_max_safety -
m_toleranceZ ) )
411 index_y += increment_index[ 1 ];
412 intersection_x += incrementX;
413 intersection_z += incrementZ;
418 index_x = ::floor( ( intersection_x - xPlane_0_min ) / szImg_X );
419 index_z = ::floor( ( intersection_z - zPlane_0_min ) / szImg_Z );
422 x2 = ( intersection_x -
mp_boundariesX[ index_x + 1 ] ) / szImg_X;
424 z2 = ( intersection_z -
mp_boundariesZ[ index_z + 1 ] ) / szImg_Z;
428 uint32_t index_final = index_x + index_y * nPlane_X + index_z * nPlane_XY;
431 INTNB index_final_pad = ( index_x + 1 ) + ( index_y + 1 ) * nPlane_X_Pad + ( index_z + 1 ) * nPlane_XY_Pad;
437 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final ) * maskIdx1, ( x1 * z1 ) * weight * maskIdx1);
438 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + 1 ) * maskIdx2, ( x2 * z1 ) * weight * maskIdx2);
439 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + nPlane_XY ) * maskIdx3, ( x1 * z2 ) * weight * maskIdx3);
440 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + 1 + nPlane_XY ) * maskIdx4, ( x2 * z2 ) * weight * maskIdx4);
443 index_y += increment_index[ 1 ];
444 intersection_x += incrementX;
445 intersection_z += incrementZ;
451 double const weight( ((
double)(ap_ProjectionLine->
GetLength())) * szImg_Z / fabs_dZ21 );
454 double const incrementZ = increment[ 2 ];
457 double const p1Z_IntersectionZ1 = ( intersection_z - event1[ 2 ] );
458 intersection_y = ( p1Z_IntersectionZ1 * dY21 / dZ21 ) + event1[ 1 ];
459 intersection_x = ( p1Z_IntersectionZ1 * dX21 / dZ21 ) + event1[ 0 ];
462 double const incrementY =
463 ( ( intersection_z + incrementZ - event1[ 2 ] ) * dY21 / dZ21 )
464 + event1[ 1 ] - intersection_y;
465 double const incrementX =
466 ( ( intersection_z + incrementZ - event1[ 2 ] ) * dX21 / dZ21 )
467 + event1[ 0 ] - intersection_x;
470 index_z = first_index[ 2 ];
473 for(
INTNB i = 0; i < nPlane_Z; ++i )
476 if( intersection_y < ( yPlane_0_min_safety +
m_toleranceY )
477 || intersection_y >= ( yPlane_N_max_safety -
m_toleranceY )
478 || intersection_x < ( xPlane_0_min_safety +
m_toleranceX )
479 || intersection_x >= ( xPlane_N_max_safety -
m_toleranceX ) )
481 index_z += increment_index[ 2 ];
482 intersection_y += incrementY;
483 intersection_x += incrementX;
488 index_y = ::floor( ( intersection_y - yPlane_0_min ) / szImg_Y );
489 index_x = ::floor( ( intersection_x - xPlane_0_min ) / szImg_X );
492 y2 = ( intersection_y -
mp_boundariesY[ index_y + 1 ] ) / szImg_Y;
494 x2 = ( intersection_x -
mp_boundariesX[ index_x + 1 ] ) / szImg_X;
498 uint32_t index_final = index_x + index_y * nPlane_X + index_z * nPlane_XY;
501 INTNB index_final_pad = ( index_x + 1 ) + ( index_y + 1 ) * nPlane_X_Pad + ( index_z + 1 ) * nPlane_XY_Pad;
507 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final ) * maskIdx1, ( x1 * y1 ) * weight * maskIdx1);
508 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + 1 ) * maskIdx2, ( x2 * y1 ) * weight * maskIdx2);
509 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + nPlane_X ) * maskIdx3, ( x1 * y2 ) * weight * maskIdx3);
510 ap_ProjectionLine->
AddVoxel(a_direction, ( index_final + nPlane_X + 1 ) * maskIdx4, ( x2 * y2 ) * weight * maskIdx4);
513 index_z += increment_index[ 2 ];
514 intersection_y += incrementY;
515 intersection_x += incrementX;
535 Cerr(
"***** iProjectorJoseph::ProjectWithTOFPos() -> Called while not initialized !" << endl);
540 #ifdef CASTOR_VERBOSE
543 string direction =
"";
544 if (a_direction==
FORWARD) direction =
"forward";
545 else direction =
"backward";
546 Cout(
"iProjectorJoseph::Project with TOF pos -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
555 double lor_length = ap_ProjectionLine->
GetLength();
570 if ( fabs(tof_deltaL) > lor_length * 0.5)
576 double lor_tof_center = lor_length * 0.5 + tof_deltaL;
579 double tof_norm_coef = tof_sigma * sqrt(2*M_PI);
582 double const dX21( event2[ 0 ] - event1[ 0 ] );
583 double const dY21( event2[ 1 ] - event1[ 1 ] );
584 double const dZ21( event2[ 2 ] - event1[ 2 ] );
587 double const fabs_dX21 = ::fabs(dX21);
588 double const fabs_dY21 = ::fabs(dY21);
589 double const fabs_dZ21 = ::fabs(dZ21);
600 INTNB const nPlane_XY( nPlane_X * nPlane_Y );
603 INTNB const nPlane_X_Pad( nPlane_X + 2 );
604 INTNB const nPlane_Y_Pad( nPlane_Y + 2 );
605 INTNB const nPlane_XY_Pad( nPlane_X_Pad * nPlane_Y_Pad );
621 double tof_center[] = {0,0,0};
623 double tof_edge_low[] = {0,0,0};
625 double tof_edge_high[] = {0,0,0};
627 INTNB tof_index_low[] = {0,0,0};
629 INTNB tof_index_high[] = {0,0,0};
632 tof_center[0] = event1[ 0 ] + lor_tof_center * dX21 / lor_length;
634 tof_edge_low[0] = tof_center[0] - tof_half_span * fabs_dX21 / lor_length;
636 tof_index_low[0] = max( (
INTNB)::floor( (tof_edge_low[0] - xPlane_0) / szImg_X ), 0);
638 if (tof_index_low[0]>nPlane_X-1)
return 0;
639 tof_edge_low[0] = (double)tof_index_low[0] * szImg_X + xPlane_0;
641 tof_edge_high[0] = tof_center[0] + tof_half_span * fabs_dX21 / lor_length;
643 tof_index_high[0] = min( (
INTNB)::floor( (tof_edge_high[0] - xPlane_0) / szImg_X ), nPlane_X-1);
645 if (tof_index_high[0]<0)
return 0;
646 tof_edge_high[0] = (double)(tof_index_high[0]+1) * szImg_X + xPlane_0;
649 tof_center[1] = event1[ 1 ] + lor_tof_center * dY21 / lor_length;
651 tof_edge_low[1] = tof_center[1] - tof_half_span * fabs_dY21 / lor_length;
652 tof_index_low[1] = max( (
INTNB)::floor( (tof_edge_low[1] - yPlane_0) / szImg_Y ), 0);
653 if (tof_index_low[1]>nPlane_Y-1)
return 0;
654 tof_edge_low[1] = (double)tof_index_low[1] * szImg_Y + yPlane_0;
656 tof_edge_high[1] = tof_center[1] + tof_half_span * fabs_dY21 / lor_length;
657 tof_index_high[1] = min( (
INTNB)::floor( (tof_edge_high[1] - yPlane_0) / szImg_Y ), nPlane_Y-1);
658 if (tof_index_high[1]<0)
return 0;
659 tof_edge_high[1] = (double)(tof_index_high[1]+1) * szImg_Y + yPlane_0;
662 tof_center[2] = event1[ 2 ] + lor_tof_center * dZ21 / lor_length;
664 tof_edge_low[2] = tof_center[2] - tof_half_span * fabs_dZ21 / lor_length;
665 tof_index_low[2] = max( (
INTNB)::floor( (tof_edge_low[2] - zPlane_0) / szImg_Z ), 0);
666 if (tof_index_low[2]>nPlane_Z-1)
return 0;
667 tof_edge_low[2] = (double)tof_index_low[2] * szImg_Z + zPlane_0;
669 tof_edge_high[2] = tof_center[2] + tof_half_span * fabs_dZ21 / lor_length;
670 tof_index_high[2] = min( (
INTNB)::floor( (tof_edge_high[2] - zPlane_0) / szImg_Z ), nPlane_Z-1);
671 if (tof_index_high[2]<0)
return 0;
672 tof_edge_high[2] = (double)(tof_index_high[2]+1) * szImg_Z + zPlane_0;
676 double intersection_x( event1[ 0 ] < xPlane_0 ?
677 tof_edge_low[0] + szImg_X / 2.0 : tof_edge_high[0] - szImg_X / 2.0 );
680 double intersection_y( event1[ 1 ] < yPlane_0 ?
681 tof_edge_low[1] + szImg_Y / 2.0 : tof_edge_high[1] - szImg_Y / 2.0 );
684 double intersection_z( event1[ 2 ] < zPlane_0 ?
685 tof_edge_low[2] + szImg_Z / 2.0 : tof_edge_high[2] - szImg_Z / 2.0 );
688 double const xPlane_0_min = xPlane_0 + szImg_X / 2.0;
689 double const yPlane_0_min = yPlane_0 + szImg_Y / 2.0;
690 double const zPlane_0_min = zPlane_0 + szImg_Z / 2.0;
693 double const xPlane_0_min_safety = xPlane_0 - ( szImg_X / 2.0 );
694 double const yPlane_0_min_safety = yPlane_0 - ( szImg_Y / 2.0 );
695 double const zPlane_0_min_safety = zPlane_0 - ( szImg_Z / 2.0 );
696 double const xPlane_N_max_safety = xPlane_N + ( szImg_X / 2.0 );
697 double const yPlane_N_max_safety = yPlane_N + ( szImg_Y / 2.0 );
698 double const zPlane_N_max_safety = zPlane_N + ( szImg_Z / 2.0 );
701 double const increment[] = {
702 event1[ 0 ] < xPlane_0 ? szImg_X : -szImg_X,
703 event1[ 1 ] < yPlane_0 ? szImg_Y : -szImg_Y,
704 event1[ 2 ] < zPlane_0 ? szImg_Z : -szImg_Z
707 INTNB const increment_index[] = {
708 event1[ 0 ] < xPlane_0 ? 1 : -1,
709 event1[ 1 ] < yPlane_0 ? 1 : -1,
710 event1[ 2 ] < zPlane_0 ? 1 : -1
713 INTNB const first_index[] = {
714 event1[ 0 ] < xPlane_0 ? (
INTNB)tof_index_low[0] : (
INTNB)tof_index_high[0],
715 event1[ 1 ] < yPlane_0 ? (
INTNB)tof_index_low[1] : (
INTNB)tof_index_high[1],
716 event1[ 2 ] < zPlane_0 ? (
INTNB)tof_index_low[2] : (
INTNB)tof_index_high[2],
721 double x1( 0.0 );
double x2( 0.0 );
722 double y1( 0.0 );
double y2( 0.0 );
723 double z1( 0.0 );
double z2( 0.0 );
727 if( fabs_dX21 >= fabs_dY21 && fabs_dX21 >= fabs_dZ21 )
730 double const incrementX = increment[ 0 ];
733 double const p1X_IntersectionX1 = ( intersection_x - event1[ 0 ] );
734 intersection_y = ( p1X_IntersectionX1 * dY21 / dX21 ) + event1[ 1 ];
735 intersection_z = ( p1X_IntersectionX1 * dZ21 / dX21 ) + event1[ 2 ];
738 double const incrementY =
739 ( ( intersection_x + incrementX - event1[ 0 ] ) * dY21 / dX21 )
740 + event1[ 1 ] - intersection_y;
741 double const incrementZ =
742 ( ( intersection_x + incrementX - event1[ 0 ] ) * dZ21 / dX21 )
743 + event1[ 2 ] - intersection_z;
746 index_x = first_index[ 0 ];
749 double previous_edge_erf = erf( ( ( intersection_x - increment_index[ 0 ] * 0.5 *szImg_X - tof_center[0]) * lor_length / fabs_dX21 ) / ( sqrt(2.)*tof_sigma ) );
750 double next_edge_erf, tof_weight;
753 for(
INTNB i = 0; i < (
INTNB)(tof_index_high[0] - tof_index_low[0] + 1); ++i )
756 if( intersection_y < ( yPlane_0_min_safety +
m_toleranceY )
757 || intersection_y >= ( yPlane_N_max_safety -
m_toleranceY )
758 || intersection_z < ( zPlane_0_min_safety +
m_toleranceZ )
759 || intersection_z >= ( zPlane_N_max_safety -
m_toleranceZ ) )
761 index_x += increment_index[ 0 ];
762 intersection_x += incrementX;
763 intersection_y += incrementY;
764 intersection_z += incrementZ;
769 index_y = ::floor( ( intersection_y - yPlane_0_min ) / szImg_Y );
770 index_z = ::floor( ( intersection_z - zPlane_0_min ) / szImg_Z );
773 y2 = ( intersection_y -
mp_boundariesY[ index_y + 1 ] ) / szImg_Y;
775 z2 = ( intersection_z -
mp_boundariesZ[ index_z + 1 ] ) / szImg_Z;
779 INTNB index_final = index_x + index_y * nPlane_X + index_z * nPlane_XY;
782 INTNB index_final_pad = ( index_x + 1 ) + ( index_y + 1 ) * nPlane_X_Pad + ( index_z + 1 ) * nPlane_XY_Pad;
786 INTNB maskIdx4 =
mp_maskPad[ index_final_pad + nPlane_X_Pad + nPlane_XY_Pad ];
789 next_edge_erf = erf( ( ( intersection_x + increment_index[ 0 ] * 0.5 * szImg_X - tof_center[0] ) * lor_length / fabs_dX21 ) / (sqrt(2.)*tof_sigma) );
791 tof_weight = 0.5 * fabs(previous_edge_erf - next_edge_erf) * tof_norm_coef ;
793 previous_edge_erf = next_edge_erf;
795 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final ) * maskIdx1, ( y1 * z1 ) * tof_weight * maskIdx1);
796 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + nPlane_X ) * maskIdx2, ( y2 * z1 ) * tof_weight * maskIdx2);
797 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + nPlane_XY ) * maskIdx3, ( y1 * z2 ) * tof_weight * maskIdx3);
798 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + nPlane_X + nPlane_XY ) * maskIdx4, ( y2 * z2 ) * tof_weight * maskIdx4);
801 index_x += increment_index[ 0 ];
802 intersection_x += incrementX;
803 intersection_y += incrementY;
804 intersection_z += incrementZ;
807 else if( fabs_dY21 > fabs_dX21 && fabs_dY21 >= fabs_dZ21 )
810 double const incrementY = increment[ 1 ];
813 double const p1Y_IntersectionY1 = ( intersection_y - event1[ 1 ] );
814 intersection_x = ( p1Y_IntersectionY1 * dX21 / dY21 ) + event1[ 0 ];
815 intersection_z = ( p1Y_IntersectionY1 * dZ21 / dY21 ) + event1[ 2 ];
818 double const incrementX =
819 ( ( intersection_y + incrementY - event1[ 1 ] ) * dX21 / dY21 )
820 + event1[ 0 ] - intersection_x;
821 double const incrementZ =
822 ( ( intersection_y + incrementY - event1[ 1 ] ) * dZ21 / dY21 )
823 + event1[ 2 ] - intersection_z;
826 index_y = first_index[ 1 ];
829 double previous_edge_erf = erf( ( ( intersection_y - increment_index[ 1 ] * 0.5 *szImg_Y - tof_center[1] ) * lor_length / fabs_dY21) / ( sqrt(2.)*tof_sigma ) );
830 double next_edge_erf, tof_weight;
833 for(
INTNB i = 0; i < (
INTNB)(tof_index_high[1] - tof_index_low[1] + 1); ++i )
836 if( intersection_x < ( xPlane_0_min_safety +
m_toleranceX )
837 || intersection_x >= ( xPlane_N_max_safety -
m_toleranceX )
838 || intersection_z < ( zPlane_0_min_safety +
m_toleranceZ )
839 || intersection_z >= ( zPlane_N_max_safety -
m_toleranceZ ) )
841 index_y += increment_index[ 1 ];
842 intersection_y += incrementY;
843 intersection_x += incrementX;
844 intersection_z += incrementZ;
849 index_x = ::floor( ( intersection_x - xPlane_0_min ) / szImg_X );
850 index_z = ::floor( ( intersection_z - zPlane_0_min ) / szImg_Z );
853 x2 = ( intersection_x -
mp_boundariesX[ index_x + 1 ] ) / szImg_X;
855 z2 = ( intersection_z -
mp_boundariesZ[ index_z + 1 ] ) / szImg_Z;
859 uint32_t index_final = index_x + index_y * nPlane_X + index_z * nPlane_XY;
862 INTNB index_final_pad = ( index_x + 1 ) + ( index_y + 1 ) * nPlane_X_Pad + ( index_z + 1 ) * nPlane_XY_Pad;
869 next_edge_erf = erf( ( ( intersection_y + increment_index[ 1 ] * 0.5 * szImg_Y - tof_center[1] ) * lor_length / fabs_dY21 ) / (sqrt(2.)*tof_sigma) );
871 tof_weight = 0.5 * fabs(previous_edge_erf - next_edge_erf) * tof_norm_coef;
873 previous_edge_erf = next_edge_erf;
875 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final ) * maskIdx1, ( x1 * z1 ) * tof_weight * maskIdx1);
876 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + 1 ) * maskIdx2, ( x2 * z1 ) * tof_weight * maskIdx2);
877 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + nPlane_XY ) * maskIdx3, ( x1 * z2 ) * tof_weight * maskIdx3);
878 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + 1 + nPlane_XY ) * maskIdx4, ( x2 * z2 ) * tof_weight * maskIdx4);
881 index_y += increment_index[ 1 ];
882 intersection_y += incrementY;
883 intersection_x += incrementX;
884 intersection_z += incrementZ;
890 double const incrementZ = increment[ 2 ];
893 double const p1Z_IntersectionZ1 = ( intersection_z - event1[ 2 ] );
894 intersection_y = ( p1Z_IntersectionZ1 * dY21 / dZ21 ) + event1[ 1 ];
895 intersection_x = ( p1Z_IntersectionZ1 * dX21 / dZ21 ) + event1[ 0 ];
898 double const incrementY =
899 ( ( intersection_z + incrementZ - event1[ 2 ] ) * dY21 / dZ21 )
900 + event1[ 1 ] - intersection_y;
901 double const incrementX =
902 ( ( intersection_z + incrementZ - event1[ 2 ] ) * dX21 / dZ21 )
903 + event1[ 0 ] - intersection_x;
906 index_z = first_index[ 2 ];
909 double previous_edge_erf = erf( ( ( intersection_z - increment_index[ 2 ] * 0.5 *szImg_Z - tof_center[2] ) * lor_length / fabs_dZ21) / ( sqrt(2.)*tof_sigma ) );
910 double next_edge_erf, tof_weight;
913 for(
INTNB i = 0; i < (
INTNB)(tof_index_high[2] - tof_index_low[2] + 1); ++i )
916 if( intersection_y < ( yPlane_0_min_safety +
m_toleranceY )
917 || intersection_y >= ( yPlane_N_max_safety -
m_toleranceY )
918 || intersection_x < ( xPlane_0_min_safety +
m_toleranceX )
919 || intersection_x >= ( xPlane_N_max_safety -
m_toleranceX ) )
921 index_z += increment_index[ 2 ];
922 intersection_z += incrementZ;
923 intersection_y += incrementY;
924 intersection_x += incrementX;
929 index_y = ::floor( ( intersection_y - yPlane_0_min ) / szImg_Y );
930 index_x = ::floor( ( intersection_x - xPlane_0_min ) / szImg_X );
933 y2 = ( intersection_y -
mp_boundariesY[ index_y + 1 ] ) / szImg_Y;
935 x2 = ( intersection_x -
mp_boundariesX[ index_x + 1 ] ) / szImg_X;
939 uint32_t index_final = index_x + index_y * nPlane_X + index_z * nPlane_XY;
942 INTNB index_final_pad = ( index_x + 1 ) + ( index_y + 1 ) * nPlane_X_Pad + ( index_z + 1 ) * nPlane_XY_Pad;
949 next_edge_erf = erf( ( ( intersection_z + increment_index[ 2 ] * 0.5 * szImg_Z - tof_center[2] ) * lor_length / fabs_dZ21 ) / (sqrt(2.)*tof_sigma) );
951 tof_weight = 0.5 * fabs(previous_edge_erf - next_edge_erf) * tof_norm_coef;
953 previous_edge_erf = next_edge_erf;
955 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final ) * maskIdx1, ( x1 * y1 ) * tof_weight * maskIdx1);
956 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + 1 ) * maskIdx2, ( x2 * y1 ) * tof_weight * maskIdx2);
957 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + nPlane_X ) * maskIdx3, ( x1 * y2 ) * tof_weight * maskIdx3);
958 ap_ProjectionLine->
AddVoxelInTOFBin(a_direction, 0, ( index_final + nPlane_X + 1 ) * maskIdx4, ( x2 * y2 ) * tof_weight * maskIdx4);
961 index_z += increment_index[ 2 ];
962 intersection_z += incrementZ;
963 intersection_y += incrementY;
964 intersection_x += incrementX;
980 Cerr(
"***** iProjectorJoseph::ProjectWithTOFBin() -> Not yet implemented !" << endl);
bool m_compatibleWithSPECTAttenuationCorrection
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
void ShowHelpSpecific()
A function used to show help about the child module.
int ProjectWithTOFPos(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
#define TWO_SQRT_TWO_LN_2
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
This class is designed to generically described any on-the-fly projector.
int ProjectWithTOFBin(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
FLTNB GetTOFMeasurement()
This function is used to get the TOF measurement.
FLTNB GetLength()
This function is used to get the length of the line.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
~iProjectorJoseph()
The destructor of iProjectorJoseph.
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...
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
Declaration of class iProjectorJoseph.
This class is designed to manage and store system matrix elements associated to a vEvent...
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project without TOF.
Declaration of class sOutputManager.
FLTNB * GetPosition2()
This function is used to get the pointer to the mp_position2 (3-values tab).
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
iProjectorJoseph()
The constructor of iProjectorJoseph.
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.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.