8 #include "iProjectorIncrementalSiddon.hh" 9 #include "sOutputManager.hh" 78 cout <<
"This projector is a simple line projector that computes the exact path length of a line through the voxels." << endl;
79 cout <<
"It is basically an incremental version of the original algorithm proposed by R. L. Siddon (see the classicSiddon projector)." << endl;
80 cout <<
"It is implemented from the following published paper:" << endl;
81 cout <<
"F. Jacobs et al, \"A fast algorithm to calculate the exact radiological path through a pixel or voxel space\", J. Comput. Inf. Technol., vol. 6, pp. 89-94, 1998." << endl;
105 if (
m_verbose>=2)
Cout(
"iProjectorIncrementalSiddon::InitializeSpecific() -> Use incremental Siddon projector" << endl);
123 max_nb_voxels_in_dimension *= 4;
125 return max_nb_voxels_in_dimension;
138 Cerr(
"***** iProjectorIncrementalSiddon::ProjectWithoutTOF() -> Called while not initialized !" << endl);
143 #ifdef CASTOR_VERBOSE 146 string direction =
"";
147 if (a_direction==
FORWARD) direction =
"forward";
148 else direction =
"backward";
149 Cout(
"iProjectorIncrementalSiddon::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
156 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
157 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
167 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
168 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
170 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
172 event2[ 0 ] - event1[ 0 ],
173 event2[ 1 ] - event1[ 1 ],
174 event2[ 2 ] - event1[ 2 ]
178 for(
int i = 0; i < 3; ++i )
180 if( delta_pos[ i ] != 0.0 )
182 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
183 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
184 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
185 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
191 if( alphaMax <= alphaMin )
return 0;
195 int iMin = 0, iMax = 0;
196 int jMin = 0, jMax = 0;
197 int kMin = 0, kMax = 0;
200 if( delta_pos[ 0 ] > 0.0f )
203 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
205 else if( delta_pos[ 0 ] < 0.0f )
208 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
210 if( delta_pos[ 0 ] == 0 )
216 if( delta_pos[ 1 ] > 0 )
219 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
221 else if( delta_pos[ 1 ] < 0 )
224 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
226 else if( delta_pos[ 1 ] == 0 )
232 if( delta_pos[ 2 ] > 0 )
235 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
237 else if( delta_pos[ 2 ] < 0 )
240 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
242 else if( delta_pos[ 2 ] == 0 )
248 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
249 + ( kMax - kMin + 1 );
252 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
255 if( delta_pos[ 0 ] > 0 )
256 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
257 else if( delta_pos[ 0 ] < 0 )
258 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
261 if( delta_pos[ 1 ] > 0 )
262 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
263 else if( delta_pos[ 1 ] < 0 )
264 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
267 if( delta_pos[ 2 ] > 0 )
268 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
269 else if( delta_pos[ 2 ] < 0 )
270 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
280 INTNB index_u[ 3 ] = {
281 (delta_pos[ 0 ] < 0) ? -1 : 1,
282 (delta_pos[ 1 ] < 0) ? -1 : 1,
283 (delta_pos[ 2 ] < 0) ? -1 : 1
287 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
288 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
289 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
292 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
293 (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
296 HPFLTNB alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
297 INTNB index_ijk[ 3 ] = {
311 for(
int nP = 0; nP < n - 1; ++nP )
313 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
314 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
317 if( ( alpha_XYZ[ 0 ] >= alphaMin )
318 && ( index_ijk[ 0 ] - 1 >= 0 )
319 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
320 && ( index_ijk[ 1 ] - 1 >= 0 )
321 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
322 && ( index_ijk[ 2 ] - 1 >= 0 )
323 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
325 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
326 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
331 alpha_c = alpha_XYZ[ 0 ];
332 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
333 index_ijk[ 0 ] += index_u[ 0 ];
335 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
336 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
339 if( ( alpha_XYZ[ 1 ] >= alphaMin )
340 && ( index_ijk[ 0 ] - 1 >= 0 )
341 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
342 && ( index_ijk[ 1 ] - 1 >= 0 )
343 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
344 && ( index_ijk[ 2 ] - 1 >= 0 )
345 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
347 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
348 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
353 alpha_c = alpha_XYZ[ 1 ];
354 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
355 index_ijk[ 1 ] += index_u[ 1 ];
357 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
358 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
361 if( ( alpha_XYZ[ 2 ] >= alphaMin )
362 && ( index_ijk[ 0 ] - 1 >= 0 )
363 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
364 && ( index_ijk[ 1 ] - 1 >= 0 )
365 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
366 && ( index_ijk[ 2 ] - 1 >= 0 )
367 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
369 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
370 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
375 alpha_c = alpha_XYZ[ 2 ];
376 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
377 index_ijk[ 2 ] += index_u[ 2 ];
394 Cerr(
"***** iProjectorIncrementalSiddon::ProjectTOFListmode() -> Called while not initialized !" << endl);
399 #ifdef CASTOR_VERBOSE 402 string direction =
"";
403 if (a_direction==
FORWARD) direction =
"forward";
404 else direction =
"backward";
405 Cout(
"iProjectorIncrementalSiddon::Project with TOF position -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
412 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
413 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
423 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
424 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
426 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
428 event2[ 0 ] - event1[ 0 ],
429 event2[ 1 ] - event1[ 1 ],
430 event2[ 2 ] - event1[ 2 ]
441 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
449 HPFLTNB lor_tof_center = length_LOR * 0.5 + tof_delta;
452 HPFLTNB tof_edge_low[] = {0,0,0};
454 HPFLTNB tof_edge_high[] = {0,0,0};
456 INTNB tof_index_low[] = {0,0,0};
457 INTNB tof_index_high[] = {0,0,0};
460 for (
int ax=0;ax<3;ax++)
463 tof_center = event1[ax] + lor_tof_center * delta_pos[ax] / length_LOR;
466 tof_edge_low[ax] = tof_center - tof_half_span * fabs(delta_pos[ax]) / length_LOR;
469 if (tof_index_low[ax]>mp_nbVox[ax]-1)
return 0;
473 tof_edge_high[ax] = tof_center + tof_half_span * fabs(delta_pos[ax]) / length_LOR;
476 if (tof_index_high[ax]<0)
return 0;
483 for(
int i = 0; i < 3; ++i )
485 if( delta_pos[ i ] != 0.0 )
487 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
488 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
489 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
490 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
496 if( alphaMax <= alphaMin )
return 0;
500 int iMin = 0, iMax = 0;
501 int jMin = 0, jMax = 0;
502 int kMin = 0, kMax = 0;
505 if( delta_pos[ 0 ] > 0.0f )
507 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMin * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
508 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
510 else if( delta_pos[ 0 ] < 0.0f )
512 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMax * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
513 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
515 if( delta_pos[ 0 ] == 0 )
521 if( delta_pos[ 1 ] > 0 )
523 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMin * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
524 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
526 else if( delta_pos[ 1 ] < 0 )
528 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMax * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
529 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
531 else if( delta_pos[ 1 ] == 0 )
537 if( delta_pos[ 2 ] > 0 )
539 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMin * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
540 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
542 else if( delta_pos[ 2 ] < 0 )
544 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMax * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
545 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
547 else if( delta_pos[ 2 ] == 0 )
553 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
554 + ( kMax - kMin + 1 );
557 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
560 if( delta_pos[ 0 ] > 0 )
561 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
562 else if( delta_pos[ 0 ] < 0 )
563 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
566 if( delta_pos[ 1 ] > 0 )
567 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
568 else if( delta_pos[ 1 ] < 0 )
569 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
572 if( delta_pos[ 2 ] > 0 )
573 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
574 else if( delta_pos[ 2 ] < 0 )
575 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
585 INTNB index_u[ 3 ] = {
586 (delta_pos[ 0 ] < 0) ? -1 : 1,
587 (delta_pos[ 1 ] < 0) ? -1 : 1,
588 (delta_pos[ 2 ] < 0) ? -1 : 1
592 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
593 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
594 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
597 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ], (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
600 HPFLTNB alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
601 INTNB index_ijk[ 3 ] = {
607 INTNB const w = mp_nbVox[ 0 ];
608 INTNB const wh = w * mp_nbVox[ 1 ];
619 for(
int nP = 0; nP < n - 1; ++nP )
621 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
622 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
625 if( ( alpha_XYZ[ 0 ] >= alphaMin )
626 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
627 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
628 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
629 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
630 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
631 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
640 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
643 alphaMid = ( alpha_XYZ[ 0 ] + alpha_c ) * 0.5;
646 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
664 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
665 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
666 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
667 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
682 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
692 alpha_c = alpha_XYZ[ 0 ];
693 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
694 index_ijk[ 0 ] += index_u[ 0 ];
696 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
697 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
700 if( ( alpha_XYZ[ 1 ] >= alphaMin )
701 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
702 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
703 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
704 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
705 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
706 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
715 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
717 alphaMid = ( alpha_XYZ[ 1 ] + alpha_c ) / 2.;
720 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
738 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
739 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
740 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
741 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
756 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
767 alpha_c = alpha_XYZ[ 1 ];
768 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
769 index_ijk[ 1 ] += index_u[ 1 ];
771 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
772 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
775 if( ( alpha_XYZ[ 2 ] >= alphaMin )
776 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
777 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
778 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
779 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
780 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
781 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
790 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
792 alphaMid = ( alpha_XYZ[ 2 ] + alpha_c ) / 2.;
795 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
813 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
814 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
815 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
816 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
831 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
842 alpha_c = alpha_XYZ[ 2 ];
843 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
844 index_ijk[ 2 ] += index_u[ 2 ];
861 Cerr(
"***** iProjectorIncrementalSiddon::ProjectTOFHistogram() -> Called while not initialized !" << endl);
866 #ifdef CASTOR_VERBOSE 869 string direction =
"";
870 if (a_direction==
FORWARD) direction =
"forward";
871 else direction =
"backward";
872 Cout(
"iProjectorIncrementalSiddon::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
879 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
880 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
886 HPFLTNB length_LOR_half = length_LOR * 0.5;
891 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
892 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
894 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
896 event2[ 0 ] - event1[ 0 ],
897 event2[ 1 ] - event1[ 1 ],
898 event2[ 2 ] - event1[ 2 ]
903 INTNB tof_half_nb_bins = tof_nb_bins/2;
907 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
913 HPFLTNB prev_erf = 0., new_erf = 0.;
916 INTNB tof_bin_last = tof_half_nb_bins;
917 INTNB tof_bin_first = -tof_half_nb_bins;
925 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
928 for(
int i = 0; i < 3; ++i )
930 if( delta_pos[ i ] != 0.0 )
932 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
933 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
934 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
935 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
941 if( alphaMax <= alphaMin )
return 0;
946 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
950 int iMin = 0, iMax = 0;
951 int jMin = 0, jMax = 0;
952 int kMin = 0, kMax = 0;
955 if( delta_pos[ 0 ] > 0.0f )
957 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMin * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
958 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
960 else if( delta_pos[ 0 ] < 0.0f )
962 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMax * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
963 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
965 if( delta_pos[ 0 ] == 0 )
971 if( delta_pos[ 1 ] > 0 )
973 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMin * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
974 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
976 else if( delta_pos[ 1 ] < 0 )
978 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMax * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
979 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
981 else if( delta_pos[ 1 ] == 0 )
987 if( delta_pos[ 2 ] > 0 )
989 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMin * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
990 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
992 else if( delta_pos[ 2 ] < 0 )
994 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMax * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
995 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
997 else if( delta_pos[ 2 ] == 0 )
1003 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
1004 + ( kMax - kMin + 1 );
1007 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
1010 if( delta_pos[ 0 ] > 0 )
1011 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
1012 else if( delta_pos[ 0 ] < 0 )
1013 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
1016 if( delta_pos[ 1 ] > 0 )
1017 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
1018 else if( delta_pos[ 1 ] < 0 )
1019 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
1022 if( delta_pos[ 2 ] > 0 )
1023 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
1024 else if( delta_pos[ 2 ] < 0 )
1025 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
1035 INTNB index_u[ 3 ] = {
1036 (delta_pos[ 0 ] < 0) ? -1 : 1,
1037 (delta_pos[ 1 ] < 0) ? -1 : 1,
1038 (delta_pos[ 2 ] < 0) ? -1 : 1
1042 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
1043 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
1044 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
1047 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ], (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
1050 HPFLTNB alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
1051 INTNB index_ijk[ 3 ] = {
1057 INTNB const w = mp_nbVox[ 0 ];
1058 INTNB const wh = w * mp_nbVox[ 1 ];
1065 for(
int nP = 0; nP < n - 1; ++nP )
1067 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
1068 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
1071 if( ( alpha_XYZ[ 0 ] >= alphaMin )
1072 && ( index_ijk[ 0 ] - 1 >= 0 )
1073 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1074 && ( index_ijk[ 1 ] - 1 >= 0 )
1075 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1076 && ( index_ijk[ 2 ] - 1 >= 0 )
1077 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1079 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1084 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
1086 alphaMid = ( alpha_XYZ[ 0 ] + alpha_c ) * 0.5;
1098 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
1099 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
1102 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1105 tof_bin_first_for_voxel += tof_half_nb_bins;
1106 tof_bin_last_for_voxel += tof_half_nb_bins;
1112 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1113 prev_erf = erf(temp/tof_sigma_sqrt2);
1118 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1138 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1139 new_erf = erf(temp/tof_sigma_sqrt2);
1140 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1150 HPFLTNB temp = ( alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1168 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1173 alpha_c = alpha_XYZ[ 0 ];
1174 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
1175 index_ijk[ 0 ] += index_u[ 0 ];
1177 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
1178 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
1181 if( ( alpha_XYZ[ 1 ] >= alphaMin )
1182 && ( index_ijk[ 0 ] - 1 >= 0 )
1183 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1184 && ( index_ijk[ 1 ] - 1 >= 0 )
1185 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1186 && ( index_ijk[ 2 ] - 1 >= 0 )
1187 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1189 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1194 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
1196 alphaMid = ( alpha_XYZ[ 1 ] + alpha_c ) * 0.5;
1202 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(floor( (alphaMid * length_LOR - tof_half_span - length_LOR_half - m_TOFBinSizeInMm/2.) / m_TOFBinSizeInMm )));
1203 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(ceil( (alphaMid * length_LOR + tof_half_span - length_LOR_half + m_TOFBinSizeInMm/2.) / m_TOFBinSizeInMm )));
1208 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) / m_TOFBinSizeInMm )));
1209 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) / m_TOFBinSizeInMm )));
1212 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1215 tof_bin_first_for_voxel += tof_half_nb_bins;
1216 tof_bin_last_for_voxel += tof_half_nb_bins;
1222 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1223 prev_erf = erf(temp/tof_sigma_sqrt2);
1228 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1248 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1249 new_erf = erf(temp/tof_sigma_sqrt2);
1250 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1260 HPFLTNB temp = ( alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1278 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1283 alpha_c = alpha_XYZ[ 1 ];
1284 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
1285 index_ijk[ 1 ] += index_u[ 1 ];
1287 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
1288 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
1291 if( ( alpha_XYZ[ 2 ] >= alphaMin )
1292 && ( index_ijk[ 0 ] - 1 >= 0 )
1293 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1294 && ( index_ijk[ 1 ] - 1 >= 0 )
1295 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1296 && ( index_ijk[ 2 ] - 1 >= 0 )
1297 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1299 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1304 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
1306 alphaMid = ( alpha_XYZ[ 2 ] + alpha_c ) * 0.5;
1312 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(floor( (alphaMid * length_LOR - tof_half_span - length_LOR_half - m_TOFBinSizeInMm/2.) / m_TOFBinSizeInMm )));
1313 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(ceil( (alphaMid * length_LOR + tof_half_span - length_LOR_half + m_TOFBinSizeInMm/2.) / m_TOFBinSizeInMm )));
1318 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) / m_TOFBinSizeInMm )));
1319 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) / m_TOFBinSizeInMm )));
1322 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1325 tof_bin_first_for_voxel += tof_half_nb_bins;
1326 tof_bin_last_for_voxel += tof_half_nb_bins;
1333 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1334 prev_erf = erf(temp/tof_sigma_sqrt2);
1339 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1359 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1360 new_erf = erf(temp/tof_sigma_sqrt2);
1361 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1371 HPFLTNB temp = ( alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1388 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1393 alpha_c = alpha_XYZ[ 2 ];
1394 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
1395 index_ijk[ 2 ] += index_u[ 2 ];
1399 delete[] tof_weights_temp;
bool m_compatibleWithSPECTAttenuationCorrection
int ProjectTOFListmode(int a_direction, oProjectionLine *ap_ProjectionLine)
~iProjectorIncrementalSiddon()
The destructor of iProjectorIncrementalSiddon.
FLTNB m_TOFGaussianNormCoef
void AddVoxelAllTOFBins(int a_direction, INTNB a_voxelIndex, FLTNB a_voxelWeight, HPFLTNB *a_tofWeights, INTNB a_tofBinFirst, INTNB a_tofBinLast)
void ShowHelpSpecific()
A function used to show help about the child module.
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.
#define SPEED_OF_LIGHT_IN_MM_PER_PS
bool m_TOFWeightingFcnPrecomputedFlag
bool m_TOFBinProperProcessingFlag
HPFLTNB * mp_TOFWeightingFcn
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
FLTNB GetLength()
This function is used to get the length of the line.
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)
int ReadConfigurationFile(const string &a_configurationFile)
FLTNB m_TOFResolutionInMm
iProjectorIncrementalSiddon()
The constructor of iProjectorIncrementalSiddon.
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
This class is designed to manage and store system matrix elements associated to a vEvent...
FLTNB m_TOFPrecomputedSamplingFactor
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
int ProjectTOFHistogram(int a_direction, oProjectionLine *ap_ProjectionLine)
int GetNbTOFBins()
This function is used to get the number of TOF bins in use.
FLTNB * GetPosition2()
This function is used to get the pointer to the mp_position2 (3-values tab).
int ReadOptionsList(const string &a_optionsList)
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
bool m_compatibleWithCompression
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
#define TWO_SQRT_TWO_LN_2
bool IsVoxelMasked(INTNB a_voxIndex)
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.
INTNB m_TOFWeightingFcnNbSamples