75 string key_word =
"number of lines sensitivity";
78 Cerr(
"***** iProjectorIncrementalSiddonMulti::ReadConfigurationFile() -> Failed to get the '" << key_word <<
"' keyword !" << endl);
82 key_word =
"number of lines reconstruction";
85 Cerr(
"***** iProjectorIncrementalSiddonMulti::ReadConfigurationFile() -> Failed to get the '" << key_word <<
"' keyword !" << endl);
106 if (
ReadStringOption(a_optionsList, option, 2,
",",
"Multi-Siddon configuration"))
108 Cerr(
"***** iProjectorIncrementalSiddonMulti::ReadConfigurationFile() -> Failed to correctly read the list of options !" << endl);
126 cout <<
"This projector uses multiple ray-tracing for a single event in order to estimate the solid angle contribution." << endl;
127 cout <<
"For each line of an event, the end points of the line are randomly chosen inside the detector element." << endl;
128 cout <<
"For PET systems, if a mean depth of interaction is given, the distribution of the random points will be centered on the provided value" << endl << endl;
129 cout <<
"The ray-tracing is performed with the incremental Siddon algorithm (see incrementalSiddon projector)." << endl;
130 cout <<
"!! IMPORTANT: This implementation has not been assessed for systems using detectors with non-zero axial angle yet." << endl;
131 cout <<
"There are 2 parameters for this projector:" << endl;
132 cout <<
" number of lines sensitivity: the number of lines used per event for the sensitivity image generation (list-mode only)." << endl;
133 cout <<
" this parameter is ignored for histogram format." << endl;
134 cout <<
" number of lines reconstruction: the number of lines used per event for the reconstruction (and histogram sensitivity image generation)" << endl << endl;
135 cout <<
"This projector can be initialized with a configuration file containing the 'number of lines sensitivity' and 'number of lines reconstruction' keywords and values" << endl;
136 cout <<
"This projector can be initialized with command line options (1st option: number of lines sensitivity, 2nd option: number of lines reconstruction" << endl;
149 Cerr(
"***** iProjectorIncrementalSiddonMulti::CheckSpecificParameters() -> The provided number of lines is less than 1 !" << endl);
164 if (
m_verbose>=2)
Cout(
"iProjectorIncrementalSiddonMulti::Initialize() -> Use incremental Siddon projector with " <<
m_nbRecoLines <<
" lines per event in reconstruction" << endl);
182 max_nb_voxels_in_dimension *= 4;
186 return max_nb_voxels_in_dimension;
199 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectWithoutTOF() -> Called while not initialized !" << endl);
204 #ifdef CASTOR_VERBOSE 207 string direction =
"";
208 if (a_direction==
FORWARD) direction =
"forward";
209 else direction =
"backward";
210 Cout(
"iProjectorIncrementalSiddonMulti::ProjectWithoutTOF() -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
220 for (uint16_t line=0; line<nb_lines; line++)
227 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectWithoutTOF() -> A problem occurred while getting positions and orientations from scanner !" << endl);
245 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
246 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
258 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
259 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
261 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
263 event2[ 0 ] - event1[ 0 ],
264 event2[ 1 ] - event1[ 1 ],
265 event2[ 2 ] - event1[ 2 ]
269 for(
int i = 0; i < 3; ++i )
271 if( delta_pos[ i ] != 0.0 )
273 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
274 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
275 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
276 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
282 if( alphaMax <= alphaMin )
return 0;
286 int iMin = 0, iMax = 0;
287 int jMin = 0, jMax = 0;
288 int kMin = 0, kMax = 0;
291 if( delta_pos[ 0 ] > 0.0f)
294 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
296 else if( delta_pos[ 0 ] < 0.0 )
299 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
301 if( delta_pos[ 0 ] == 0 )
307 if( delta_pos[ 1 ] > 0 )
310 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
312 else if( delta_pos[ 1 ] < 0 )
315 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
317 else if( delta_pos[ 1 ] == 0 )
323 if( delta_pos[ 2 ] > 0 )
326 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
328 else if( delta_pos[ 2 ] < 0 )
331 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
333 else if( delta_pos[ 2 ] == 0 )
339 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
340 + ( kMax - kMin + 1 );
343 HPFLTNB alpha_XYZ[ 3 ] = { 1.0, 1.0, 1.0 };
346 if( delta_pos[ 0 ] > 0 )
347 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
348 else if( delta_pos[ 0 ] < 0 )
349 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
352 if( delta_pos[ 1 ] > 0 )
353 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
354 else if( delta_pos[ 1 ] < 0 )
355 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
358 if( delta_pos[ 2 ] > 0 )
359 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
360 else if( delta_pos[ 2 ] < 0 )
361 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
371 INTNB index_u[ 3 ] = {
372 (delta_pos[ 0 ] < 0) ? -1 : 1,
373 (delta_pos[ 1 ] < 0) ? -1 : 1,
374 (delta_pos[ 2 ] < 0) ? -1 : 1
378 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
379 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
380 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
383 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ],
384 (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
387 HPFLTNB const alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
388 INTNB index_ijk[ 3 ] = {
402 for(
int nP = 0; nP < n - 1; ++nP )
404 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
405 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
408 if( ( alpha_XYZ[ 0 ] >= alphaMin )
409 && ( index_ijk[ 0 ] - 1 >= 0 )
410 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
411 && ( index_ijk[ 1 ] - 1 >= 0 )
412 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
413 && ( index_ijk[ 2 ] - 1 >= 0 )
414 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
416 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
417 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
422 alpha_c = alpha_XYZ[ 0 ];
423 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
424 index_ijk[ 0 ] += index_u[ 0 ];
426 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
427 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
430 if( ( alpha_XYZ[ 1 ] >= alphaMin )
431 && ( index_ijk[ 0 ] - 1 >= 0 )
432 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
433 && ( index_ijk[ 1 ] - 1 >= 0 )
434 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
435 && ( index_ijk[ 2 ] - 1 >= 0 )
436 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
438 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
439 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
444 alpha_c = alpha_XYZ[ 1 ];
445 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
446 index_ijk[ 1 ] += index_u[ 1 ];
448 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
449 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
452 if( ( alpha_XYZ[ 2 ] >= alphaMin )
453 && ( index_ijk[ 0 ] - 1 >= 0 )
454 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
455 && ( index_ijk[ 1 ] - 1 >= 0 )
456 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
457 && ( index_ijk[ 2 ] - 1 >= 0 )
458 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
460 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
461 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
467 alpha_c = alpha_XYZ[ 2 ];
468 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
469 index_ijk[ 2 ] += index_u[ 2 ];
487 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectTOFListmode() -> Called while not initialized !" << endl);
492 #ifdef CASTOR_VERBOSE 495 string direction =
"";
496 if (a_direction==
FORWARD) direction =
"forward";
497 else direction =
"backward";
498 Cout(
"iProjectorIncrementalSiddonMulti::ProjectTOFListmode() -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
508 for (uint16_t line=0; line<nb_lines; line++)
515 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectTOFListmode() -> A problem occurred while getting positions and orientations from scanner !" << endl);
533 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
534 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
546 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
547 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
549 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
551 event2[ 0 ] - event1[ 0 ],
552 event2[ 1 ] - event1[ 1 ],
553 event2[ 2 ] - event1[ 2 ]
564 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
572 HPFLTNB lor_tof_center = length_LOR * 0.5 + tof_delta;
575 HPFLTNB tof_edge_low[] = {0,0,0};
577 HPFLTNB tof_edge_high[] = {0,0,0};
579 INTNB tof_index_low[] = {0,0,0};
580 INTNB tof_index_high[] = {0,0,0};
583 for (
int ax=0;ax<3;ax++)
586 tof_center = event1[ax] + lor_tof_center * delta_pos[ax] / length_LOR;
589 tof_edge_low[ax] = tof_center - tof_half_span * fabs(delta_pos[ax]) / length_LOR;
592 if (tof_index_low[ax]>
mp_nbVox[ax]-1)
return 0;
596 tof_edge_high[ax] = tof_center + tof_half_span * fabs(delta_pos[ax]) / length_LOR;
599 if (tof_index_high[ax]<0)
return 0;
606 for(
int i = 0; i < 3; ++i )
608 if( delta_pos[ i ] != 0.0 )
610 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
611 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
612 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
613 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
619 if( alphaMax <= alphaMin )
return 0;
623 int iMin = 0, iMax = 0;
624 int jMin = 0, jMax = 0;
625 int kMin = 0, kMax = 0;
628 if( delta_pos[ 0 ] > 0.0f )
631 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
633 else if( delta_pos[ 0 ] < 0.0f )
636 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
638 if( delta_pos[ 0 ] == 0 )
644 if( delta_pos[ 1 ] > 0 )
647 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
649 else if( delta_pos[ 1 ] < 0 )
652 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
654 else if( delta_pos[ 1 ] == 0 )
660 if( delta_pos[ 2 ] > 0 )
663 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
665 else if( delta_pos[ 2 ] < 0 )
668 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
670 else if( delta_pos[ 2 ] == 0 )
676 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
677 + ( kMax - kMin + 1 );
680 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
683 if( delta_pos[ 0 ] > 0 )
684 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
685 else if( delta_pos[ 0 ] < 0 )
686 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
689 if( delta_pos[ 1 ] > 0 )
690 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
691 else if( delta_pos[ 1 ] < 0 )
692 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
695 if( delta_pos[ 2 ] > 0 )
696 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
697 else if( delta_pos[ 2 ] < 0 )
698 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
708 INTNB index_u[ 3 ] = {
709 (delta_pos[ 0 ] < 0) ? -1 : 1,
710 (delta_pos[ 1 ] < 0) ? -1 : 1,
711 (delta_pos[ 2 ] < 0) ? -1 : 1
715 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
716 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
717 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
720 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ], (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
723 HPFLTNB alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
724 INTNB index_ijk[ 3 ] = {
742 for(
int nP = 0; nP < n - 1; ++nP )
744 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
745 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
748 if( ( alpha_XYZ[ 0 ] >= alphaMin )
749 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
750 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
751 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
752 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
753 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
754 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
763 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
766 alphaMid = ( alpha_XYZ[ 0 ] + alpha_c ) * 0.5;
769 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
787 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
788 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
789 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
790 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
805 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
815 alpha_c = alpha_XYZ[ 0 ];
816 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
817 index_ijk[ 0 ] += index_u[ 0 ];
819 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
820 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
823 if( ( alpha_XYZ[ 1 ] >= alphaMin )
824 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
825 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
826 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
827 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
828 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
829 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
838 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
840 alphaMid = ( alpha_XYZ[ 1 ] + alpha_c ) / 2.;
843 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
861 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
862 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
863 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
864 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
879 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
890 alpha_c = alpha_XYZ[ 1 ];
891 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
892 index_ijk[ 1 ] += index_u[ 1 ];
894 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
895 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
898 if( ( alpha_XYZ[ 2 ] >= alphaMin )
899 && ( index_ijk[ 0 ] - 1 >= tof_index_low[0] )
900 && ( index_ijk[ 0 ] - 1 <= tof_index_high[0] )
901 && ( index_ijk[ 1 ] - 1 >= tof_index_low[1] )
902 && ( index_ijk[ 1 ] - 1 <= tof_index_high[1] )
903 && ( index_ijk[ 2 ] - 1 >= tof_index_low[2] )
904 && ( index_ijk[ 2 ] - 1 <= tof_index_high[2] ) )
913 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
915 alphaMid = ( alpha_XYZ[ 2 ] + alpha_c ) / 2.;
918 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
936 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
937 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
938 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
939 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
954 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
965 alpha_c = alpha_XYZ[ 2 ];
966 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
967 index_ijk[ 2 ] += index_u[ 2 ];
985 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectTOFHistogram() -> Called while not initialized !" << endl);
990 #ifdef CASTOR_VERBOSE 993 string direction =
"";
994 if (a_direction==
FORWARD) direction =
"forward";
995 else direction =
"backward";
996 Cout(
"iProjectorIncrementalSiddonMulti::ProjectTOFHistogram() -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
1006 for (uint16_t line=0; line<nb_lines; line++)
1013 Cerr(
"***** iProjectorIncrementalSiddonMulti::ProjectTOFHistogram() -> A problem occurred while getting positions and orientations from scanner !" << endl);
1031 HPFLTNB event1[3] = { event1Float[0], event1Float[1], event1Float[2] };
1032 HPFLTNB event2[3] = { event2Float[0], event2Float[1], event2Float[2] };
1040 HPFLTNB length_LOR_half = length_LOR * 0.5;
1045 HPFLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
1046 HPFLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
1048 HPFLTNB alphaMin = 0.0f, alphaMax = 1.0f;
1050 event2[ 0 ] - event1[ 0 ],
1051 event2[ 1 ] - event1[ 1 ],
1052 event2[ 2 ] - event1[ 2 ]
1057 INTNB tof_half_nb_bins = tof_nb_bins/2;
1061 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
1067 HPFLTNB prev_erf = 0., new_erf = 0.;
1070 INTNB tof_bin_last = tof_half_nb_bins;
1071 INTNB tof_bin_first = -tof_half_nb_bins;
1079 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
1082 for(
int i = 0; i < 3; ++i )
1084 if( delta_pos[ i ] != 0.0 )
1086 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
1087 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
1088 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
1089 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
1095 if( alphaMax <= alphaMin )
return 0;
1100 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
1104 int iMin = 0, iMax = 0;
1105 int jMin = 0, jMax = 0;
1106 int kMin = 0, kMax = 0;
1109 if( delta_pos[ 0 ] > 0.0f )
1112 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
1114 else if( delta_pos[ 0 ] < 0.0f )
1117 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
1119 if( delta_pos[ 0 ] == 0 )
1125 if( delta_pos[ 1 ] > 0 )
1128 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
1130 else if( delta_pos[ 1 ] < 0 )
1133 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
1135 else if( delta_pos[ 1 ] == 0 )
1141 if( delta_pos[ 2 ] > 0 )
1144 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
1146 else if( delta_pos[ 2 ] < 0 )
1149 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
1151 else if( delta_pos[ 2 ] == 0 )
1157 INTNB n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
1158 + ( kMax - kMin + 1 );
1161 HPFLTNB alpha_XYZ[ 3 ] = { 1.0f, 1.0f, 1.0f };
1164 if( delta_pos[ 0 ] > 0 )
1165 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMin - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
1166 else if( delta_pos[ 0 ] < 0 )
1167 alpha_XYZ[ 0 ] = ( ( (-
mp_halfFOV[ 0 ]) + ( iMax - 1 ) *
mp_sizeVox[0] ) - event1[ 0 ] ) / delta_pos[ 0 ];
1170 if( delta_pos[ 1 ] > 0 )
1171 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMin - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
1172 else if( delta_pos[ 1 ] < 0 )
1173 alpha_XYZ[ 1 ] = ( ( (-
mp_halfFOV[ 1 ]) + ( jMax - 1 ) *
mp_sizeVox[1] ) - event1[ 1 ] ) / delta_pos[ 1 ];
1176 if( delta_pos[ 2 ] > 0 )
1177 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMin - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
1178 else if( delta_pos[ 2 ] < 0 )
1179 alpha_XYZ[ 2 ] = ( ( (-
mp_halfFOV[ 2 ]) + ( kMax - 1 ) *
mp_sizeVox[2] ) - event1[ 2 ] ) / delta_pos[ 2 ];
1189 INTNB index_u[ 3 ] = {
1190 (delta_pos[ 0 ] < 0) ? -1 : 1,
1191 (delta_pos[ 1 ] < 0) ? -1 : 1,
1192 (delta_pos[ 2 ] < 0) ? -1 : 1
1196 if( alpha_XYZ[ 0 ] == alphaMin ) alpha_XYZ[ 0 ] += alpha_u[ 0 ];
1197 if( alpha_XYZ[ 1 ] == alphaMin ) alpha_XYZ[ 1 ] += alpha_u[ 1 ];
1198 if( alpha_XYZ[ 2 ] == alphaMin ) alpha_XYZ[ 2 ] += alpha_u[ 2 ];
1201 HPFLTNB const min_alpha_XYZ = (std::min)( alpha_XYZ[ 0 ], (std::min)( alpha_XYZ[ 1 ], alpha_XYZ[ 2 ] ) );
1204 HPFLTNB alphaMid = ( min_alpha_XYZ + alphaMin ) / 2.0f;
1205 INTNB index_ijk[ 3 ] = {
1219 for(
int nP = 0; nP < n - 1; ++nP )
1221 if( ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 1 ] )
1222 && ( alpha_XYZ[ 0 ] <= alpha_XYZ[ 2 ] ) )
1225 if( ( alpha_XYZ[ 0 ] >= alphaMin )
1226 && ( index_ijk[ 0 ] - 1 >= 0 )
1227 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1228 && ( index_ijk[ 1 ] - 1 >= 0 )
1229 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1230 && ( index_ijk[ 2 ] - 1 >= 0 )
1231 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1233 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1238 coeff = ( alpha_XYZ[ 0 ] - alpha_c ) * length_LOR;
1240 alphaMid = ( alpha_XYZ[ 0 ] + alpha_c ) * 0.5;
1252 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
1253 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
1256 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1259 tof_bin_first_for_voxel += tof_half_nb_bins;
1260 tof_bin_last_for_voxel += tof_half_nb_bins;
1266 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1267 prev_erf = erf(temp/tof_sigma_sqrt2);
1272 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1292 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1293 new_erf = erf(temp/tof_sigma_sqrt2);
1294 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1304 HPFLTNB temp = ( alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1322 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1327 alpha_c = alpha_XYZ[ 0 ];
1328 alpha_XYZ[ 0 ] += alpha_u[ 0 ];
1329 index_ijk[ 0 ] += index_u[ 0 ];
1331 else if( ( alpha_XYZ[ 1 ] < alpha_XYZ[ 0 ] )
1332 && ( alpha_XYZ[ 1 ] <= alpha_XYZ[ 2 ] ) )
1335 if( ( alpha_XYZ[ 1 ] >= alphaMin )
1336 && ( index_ijk[ 0 ] - 1 >= 0 )
1337 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1338 && ( index_ijk[ 1 ] - 1 >= 0 )
1339 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1340 && ( index_ijk[ 2 ] - 1 >= 0 )
1341 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1343 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1348 coeff = ( alpha_XYZ[ 1 ] - alpha_c ) * length_LOR;
1350 alphaMid = ( alpha_XYZ[ 1 ] + alpha_c ) * 0.5;
1362 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
1363 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
1366 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1369 tof_bin_first_for_voxel += tof_half_nb_bins;
1370 tof_bin_last_for_voxel += tof_half_nb_bins;
1376 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1377 prev_erf = erf(temp/tof_sigma_sqrt2);
1382 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1402 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1403 new_erf = erf(temp/tof_sigma_sqrt2);
1404 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1414 HPFLTNB temp = ( alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1432 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1437 alpha_c = alpha_XYZ[ 1 ];
1438 alpha_XYZ[ 1 ] += alpha_u[ 1 ];
1439 index_ijk[ 1 ] += index_u[ 1 ];
1441 else if( ( alpha_XYZ[ 2 ] < alpha_XYZ[ 0 ] )
1442 && ( alpha_XYZ[ 2 ] < alpha_XYZ[ 1 ] ) )
1445 if( ( alpha_XYZ[ 2 ] >= alphaMin )
1446 && ( index_ijk[ 0 ] - 1 >= 0 )
1447 && ( index_ijk[ 0 ] - 1 <= mp_nbVox[ 0 ] - 1 )
1448 && ( index_ijk[ 1 ] - 1 >= 0 )
1449 && ( index_ijk[ 1 ] - 1 <= mp_nbVox[ 1 ] - 1 )
1450 && ( index_ijk[ 2 ] - 1 >= 0 )
1451 && ( index_ijk[ 2 ] - 1 <= mp_nbVox[ 2 ] - 1 ) )
1453 numVox = ( index_ijk[ 0 ] - 1 ) + ( ( index_ijk[ 1 ] - 1 ) ) * w + ( ( index_ijk[ 2 ] - 1 ) ) * wh;
1458 coeff = ( alpha_XYZ[ 2 ] - alpha_c ) * length_LOR;
1460 alphaMid = ( alpha_XYZ[ 2 ] + alpha_c ) * 0.5;
1472 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
1473 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
1476 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1479 tof_bin_first_for_voxel += tof_half_nb_bins;
1480 tof_bin_last_for_voxel += tof_half_nb_bins;
1487 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1488 prev_erf = erf(temp/tof_sigma_sqrt2);
1493 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1513 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1514 new_erf = erf(temp/tof_sigma_sqrt2);
1515 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1525 HPFLTNB temp = ( alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1542 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1547 alpha_c = alpha_XYZ[ 2 ];
1548 alpha_XYZ[ 2 ] += alpha_u[ 2 ];
1549 index_ijk[ 2 ] += index_u[ 2 ];
1552 delete[] tof_weights_temp;
void ShowHelpSpecific()
A function used to show help about the child module.
bool m_compatibleWithSPECTAttenuationCorrection
FLTNB * GetOrientation1()
This function is used to get the pointer to the mp_orientation1 (3-values tab).
int ReadConfigurationFile(const string &a_configurationFile)
A function used to read options from a configuration file.
#define SPEED_OF_LIGHT_IN_MM_PER_PS
FLTNB m_TOFGaussianNormCoef
void AddVoxelAllTOFBins(int a_direction, INTNB a_voxelIndex, FLTNB a_voxelWeight, HPFLTNB *a_tofWeights, INTNB a_tofBinFirst, INTNB a_tofBinLast)
Add a voxel contribution to the line for all relevant TOF bins.
#define TWO_SQRT_TWO_LN_2
oImageDimensionsAndQuantification * mp_ImageDimensionsAndQuantification
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.
bool m_TOFWeightingFcnPrecomputedFlag
int InitializeSpecific()
This function is used to initialize specific stuff to the child projector.
bool m_TOFBinProperProcessingFlag
HPFLTNB * mp_TOFWeightingFcn
FLTNB GetLength()
This function is used to get the length of the line.
FLTNB * GetOrientation2()
This function is used to get the pointer to the mp_orientation2 (3-values tab).
void ComputeLineLength()
Simply compute and update the m_length using the associated mp_position1 and mp_position2.
int GetIndex2()
This function is used to get the index associated to point 2.
void ApplyOffset()
Apply the offset of oImageDimensionsAndQuantification to the mp_position1 and mp_position2.
FLTNB * GetPosition1()
This function is used to get the pointer to the mp_position1 (3-values tab).
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
void AddVoxel(int a_direction, INTNB a_voxelIndice, FLTNB a_voxelWeight)
This function is used to add a voxel contribution to the line, assuming TOF bin 0 (i...
int ReadDataASCIIFile(const string &a_file, const string &a_keyword, T *ap_return, int a_nbElts, bool a_mandatoryFlag)
Look for "a_nbElts" elts in the "a_file" file matching the "a_keyword" string passed as parameter a...
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
FLTNB m_TOFResolutionInMm
Declaration of class iProjectorIncrementalSiddonMulti.
#define KEYWORD_MANDATORY
virtual int GetRdmPositionsAndOrientations(int a_index1, int a_index2, FLTNB ap_Position1[3], FLTNB ap_Position2[3], FLTNB ap_Orientation1[3], FLTNB ap_Orientation2[3])=0
This is a pure virtual method that must be implemented by children. Get random positions of the sca...
~iProjectorIncrementalSiddonMulti()
The destructor of iProjectorIncrementalSiddonMulti.
This class is designed to manage and store system matrix elements associated to a vEvent...
FLTNB m_TOFPrecomputedSamplingFactor
int ProjectTOFListmode(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF continuous information.
Declaration of class sOutputManager.
int GetNbTOFBins()
This function is used to get the number of TOF bins in use.
iProjectorIncrementalSiddonMulti()
The constructor of iProjectorIncrementalSiddonMulti.
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.
int ReadOptionsList(const string &a_optionsList)
A function used to read options from a list of options.
bool m_compatibleWithCompression
int ProjectTOFHistogram(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project with TOF binned information.
int GetIndex1()
This function is used to get the index associated to point 1.
int ReadStringOption(const string &a_input, T *ap_return, int a_nbElts, const string &sep, const string &a_option)
Parse the 'a_input' string corresponding to the 'a_option' into 'a_nbElts' elements, using the 'sep' separator. The results are returned in the templated 'ap_return' dynamic templated array. Call "ConvertFromString()" to perform the correct conversion depending on the type of the data to convert.
void ApplyBedOffset()
Apply the bed offset of m_bedOffset to the mp_position1 and mp_position2.
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
A function to project without TOF.
INTNB GetNbVoxY()
Get the number of voxels along the Y axis.
INTNB m_TOFWeightingFcnNbSamples