12 #include "iProjectorClassicSiddon.hh" 13 #include "sOutputManager.hh" 79 cout <<
"This projector is a simple line projector that computes the exact path length of a line through the voxels." << endl;
80 cout <<
"It is implemented from the following published paper:" << endl;
81 cout <<
"R. L. Siddon, \"Fast calculation of the exact radiological path for a three-dimensional CT array\", Med. Phys., vol. 12, pp. 252-5, 1985." << endl;
82 cout <<
"All voxels are correctly ordered in the line, so this projector can be used with SPECT attenuation correction." << endl;
106 if (
m_verbose>=2)
Cout(
"iProjectorClassicSiddon::InitializeSpecific() -> Use classic Siddon projector" << endl);
124 max_nb_voxels_in_dimension *= 4;
126 return max_nb_voxels_in_dimension;
139 Cerr(
"***** iProjectorClassicSiddon::ProjectWithoutTOF() -> Called while not initialized !" << endl);
144 #ifdef CASTOR_VERBOSE 147 string direction =
"";
148 if (a_direction==
FORWARD) direction =
"forward";
149 else direction =
"backward";
150 Cout(
"iProjectorClassicSiddon::Project without TOF -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
158 FLTNB event1[3] = { event1_position[0], event1_position[1], event1_position[2] };
159 FLTNB event2[3] = { event2_position[0], event2_position[1], event2_position[2] };
169 FLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
170 FLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
172 FLTNB alphaMin = 0.0, alphaMax = 1.0;
173 FLTNB delta_pos[] = {
174 event2[ 0 ] - event1[ 0 ],
175 event2[ 1 ] - event1[ 1 ],
176 event2[ 2 ] - event1[ 2 ]
180 for(
int i = 0; i < 3; ++i )
182 if( delta_pos[ i ] != 0.0 )
184 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
185 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
186 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
187 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
193 if( alphaMax <= alphaMin )
return 0;
197 int iMin = 0, iMax = 0;
198 int jMin = 0, jMax = 0;
199 int kMin = 0, kMax = 0;
202 if( delta_pos[ 0 ] > 0.0 )
205 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
207 else if( delta_pos[ 0 ] < 0.0 )
210 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
212 if( delta_pos[ 0 ] == 0. )
218 if( delta_pos[ 1 ] > 0. )
221 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
223 else if( delta_pos[ 1 ] < 0. )
226 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
228 else if( delta_pos[ 1 ] == 0. )
234 if( delta_pos[ 2 ] > 0. )
237 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
239 else if( delta_pos[ 2 ] < 0. )
242 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
244 else if( delta_pos[ 2 ] == 0. )
250 int n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
251 + ( kMax - kMin + 1 );
256 FLTNB *tmpAlpha =
new FLTNB[ mp_nbVox[ 0 ] + mp_nbVox[ 1 ] + mp_nbVox[ 2 ] + 3 ];
257 FLTNB *alphaX =
new FLTNB[ ( mp_nbVox[ 0 ] + 1 ) ];
258 FLTNB *alphaY =
new FLTNB[ ( mp_nbVox[ 1 ] + 1 ) ];
259 FLTNB *alphaZ =
new FLTNB[ ( mp_nbVox[ 2 ] + 1 ) ];
261 INTNB iElement = iMax - iMin + 1;
265 if( delta_pos[ 0 ] > 0. )
267 for(
int i = iMin; i <= iMax; ++i )
270 else if( delta_pos[ 0 ] < 0. )
272 for(
int i = iMax; i >= iMin; --i )
278 INTNB jElement = jMax - jMin + 1;
282 if( delta_pos[ 1 ] > 0. )
284 for(
int j = jMin; j <= jMax; ++j )
287 else if( delta_pos[ 1 ] < 0. )
289 for(
int j = jMax; j >= jMin; --j )
295 INTNB kElement = kMax - kMin + 1;
299 if( delta_pos[ 2 ] > 0. )
301 for(
int k = kMin; k <= kMax; ++k )
304 else if( delta_pos[ 2 ] < 0. )
306 for(
int k = kMax; k >= kMin; --k )
312 alphaX, alphaX + iElement,
316 ::memcpy( tmpAlpha, alpha, ( iElement ) *
sizeof(
FLTNB ) );
319 alphaY, alphaY + jElement,
320 tmpAlpha, tmpAlpha + iElement,
323 ::memcpy( tmpAlpha, alpha, ( iElement + jElement ) *
sizeof(
FLTNB ) );
326 alphaZ, alphaZ + kElement,
327 tmpAlpha, tmpAlpha + iElement + jElement,
339 FLTNB alphaMid = 0.0;
340 INTNB i = 0, j = 0, k = 0;
341 FLTNB *pAlpha = &alpha[ 1 ];
342 FLTNB *pAlphaPrevious = &alpha[ 0 ];
346 for(
int nP = 0; nP < n - 1; ++nP, ++pAlpha, ++pAlphaPrevious )
348 alphaMid = ( *pAlpha + *pAlphaPrevious ) * 0.5;
350 i = alphaMid * i2 + i1;
351 if( i < 1 || i > mp_nbVox[ 0 ] )
continue;
353 j = alphaMid * j2 + j1;
354 if( j < 1 || j > mp_nbVox[ 1 ] )
continue;
356 k = alphaMid * k2 + k1;
357 if( k < 1 || k > mp_nbVox[ 2 ] )
continue;
359 numVox = ( i - 1 ) + ( j - 1 ) * mp_nbVox[0] + ( k - 1 ) * mp_nbVox[0] * mp_nbVox[1];
364 coeff = length_LOR * ( *pAlpha - *pAlphaPrevious );
366 ap_ProjectionLine->
AddVoxel(a_direction, numVox, coeff);
375 #ifdef CASTOR_VERBOSE 378 Cout(
"iProjectorClassicSiddon::Project without TOF -> Exit function" << endl);
395 Cerr(
"***** iProjectorClassicSiddon::ProjectTOFListmode() -> Called while not initialized !" << endl);
400 #ifdef CASTOR_VERBOSE 403 string direction =
"";
404 if (a_direction==
FORWARD) direction =
"forward";
405 else direction =
"backward";
406 Cout(
"iProjectorClassicSiddon::Project with TOF measurement -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
414 FLTNB event1[3] = { event1_position[0], event1_position[1], event1_position[2] };
415 FLTNB event2[3] = { event2_position[0], event2_position[1], event2_position[2] };
425 FLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
426 FLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
428 FLTNB alphaMin = 0.0, alphaMax = 1.0;
429 FLTNB delta_pos[] = {
430 event2[ 0 ] - event1[ 0 ],
431 event2[ 1 ] - event1[ 1 ],
432 event2[ 2 ] - event1[ 2 ]
443 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
451 HPFLTNB lor_tof_center = length_LOR * 0.5 + tof_delta;
454 HPFLTNB tof_edge_low[] = {0,0,0};
456 HPFLTNB tof_edge_high[] = {0,0,0};
461 for (
int ax=0;ax<3;ax++)
464 tof_center = event1[ax] + lor_tof_center * delta_pos[ax] / length_LOR;
467 tof_edge_low[ax] = tof_center - tof_half_span * fabs(delta_pos[ax]) / length_LOR;
470 if (tof_index>mp_nbVox[ax]-1)
return 0;
474 tof_edge_high[ax] = tof_center + tof_half_span * fabs(delta_pos[ax]) / length_LOR;
477 if (tof_index<0)
return 0;
484 for(
int i = 0; i < 3; ++i )
486 if( delta_pos[ i ] != 0.0 )
488 alphaFirst[i] = (tof_edge_low[i] - event1[i]) / (delta_pos[ i ]);
489 alphaLast[i] = (tof_edge_high[i] - event1[i]) / (delta_pos[ i ]);
490 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
491 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
497 if( alphaMax <= alphaMin )
return 0;
501 int iMin = 0, iMax = 0;
502 int jMin = 0, jMax = 0;
503 int kMin = 0, kMax = 0;
506 if( delta_pos[ 0 ] > 0.0 )
508 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMin * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
509 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
511 else if( delta_pos[ 0 ] < 0.0 )
513 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMax * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
514 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
516 if( delta_pos[ 0 ] == 0. )
522 if( delta_pos[ 1 ] > 0. )
524 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMin * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
525 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
527 else if( delta_pos[ 1 ] < 0. )
529 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMax * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
530 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
532 else if( delta_pos[ 1 ] == 0. )
538 if( delta_pos[ 2 ] > 0. )
540 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMin * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
541 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
543 else if( delta_pos[ 2 ] < 0. )
545 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMax * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
546 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
548 else if( delta_pos[ 2 ] == 0. )
554 int n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
555 + ( kMax - kMin + 1 );
559 FLTNB *alpha =
new FLTNB[ mp_nbVox[ 0 ] + mp_nbVox[ 1 ] + mp_nbVox[ 2 ] + 3 ];
560 FLTNB *tmpAlpha =
new FLTNB[ mp_nbVox[ 0 ] + mp_nbVox[ 1 ] + mp_nbVox[ 2 ] + 3 ];
561 FLTNB *alphaX =
new FLTNB[ ( mp_nbVox[ 0 ] + 1 ) ];
562 FLTNB *alphaY =
new FLTNB[ ( mp_nbVox[ 1 ] + 1 ) ];
563 FLTNB *alphaZ =
new FLTNB[ ( mp_nbVox[ 2 ] + 1 ) ];
565 INTNB iElement = iMax - iMin + 1;
569 if( delta_pos[ 0 ] > 0. )
571 for(
int i = iMin; i <= iMax; ++i )
574 else if( delta_pos[ 0 ] < 0. )
576 for(
int i = iMax; i >= iMin; --i )
582 INTNB jElement = jMax - jMin + 1;
586 if( delta_pos[ 1 ] > 0. )
588 for(
int j = jMin; j <= jMax; ++j )
591 else if( delta_pos[ 1 ] < 0. )
593 for(
int j = jMax; j >= jMin; --j )
599 INTNB kElement = kMax - kMin + 1;
603 if( delta_pos[ 2 ] > 0. )
605 for(
int k = kMin; k <= kMax; ++k )
608 else if( delta_pos[ 2 ] < 0. )
610 for(
int k = kMax; k >= kMin; --k )
616 alphaX, alphaX + iElement,
620 ::memcpy( tmpAlpha, alpha, ( iElement ) *
sizeof(
FLTNB ) );
623 alphaY, alphaY + jElement,
624 tmpAlpha, tmpAlpha + iElement,
627 ::memcpy( tmpAlpha, alpha, ( iElement + jElement ) *
sizeof(
FLTNB ) );
630 alphaZ, alphaZ + kElement,
631 tmpAlpha, tmpAlpha + iElement + jElement,
643 FLTNB alphaMid = 0.0;
644 INTNB i = 0, j = 0, k = 0;
645 FLTNB *pAlpha = &alpha[ 1 ];
646 FLTNB *pAlphaPrevious = &alpha[ 0 ];
655 for(
int nP = 0; nP < n - 1; ++nP, ++pAlpha, ++pAlphaPrevious )
657 alphaMid = ( *pAlpha + *pAlphaPrevious ) * 0.5;
659 i = alphaMid * i2 + i1;
660 if( i < 1 || i > mp_nbVox[ 0 ] )
continue;
662 j = alphaMid * j2 + j1;
663 if( j < 1 || j > mp_nbVox[ 1 ] )
continue;
665 k = alphaMid * k2 + k1;
666 if( k < 1 || k > mp_nbVox[ 2 ] )
continue;
668 numVox = ( i - 1 ) + ( j - 1 ) * mp_nbVox[0] + ( k - 1 ) * mp_nbVox[0] * mp_nbVox[1];
671 coeff = length_LOR * ( *pAlpha - *pAlphaPrevious );
689 HPFLTNB temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center -
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
690 HPFLTNB prev_erf = erf(temp_erf/tof_sigma_sqrt2);
691 temp_erf = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center +
m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
692 HPFLTNB new_erf = erf(temp_erf/tof_sigma_sqrt2);
707 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
723 #ifdef CASTOR_VERBOSE 726 Cout(
"iProjectorClassicSiddon::Project with TOF measurement-> Exit function" << endl);
743 Cerr(
"***** iProjectorClassicSiddon::ProjectTOFHistogram() -> Called while not initialized !" << endl);
748 #ifdef CASTOR_VERBOSE 751 string direction =
"";
752 if (a_direction==
FORWARD) direction =
"forward";
753 else direction =
"backward";
754 Cout(
"iProjectorClassicSiddon::Project with TOF bins -> Project line '" << ap_ProjectionLine <<
"' in " << direction <<
" direction" << endl);
762 FLTNB event1[3] = { event1_position[0], event1_position[1], event1_position[2] };
763 FLTNB event2[3] = { event2_position[0], event2_position[1], event2_position[2] };
769 FLTNB length_LOR_half = length_LOR * 0.5;
774 FLTNB alphaFirst[] = { 0.0, 0.0, 0.0 };
775 FLTNB alphaLast[] = { 0.0, 0.0, 0.0 };
777 FLTNB alphaMin = 0.0, alphaMax = 1.0;
778 FLTNB delta_pos[] = {
779 event2[ 0 ] - event1[ 0 ],
780 event2[ 1 ] - event1[ 1 ],
781 event2[ 2 ] - event1[ 2 ]
786 INTNB tof_half_nb_bins = tof_nb_bins/2;
790 HPFLTNB tof_sigma_sqrt2 = sqrt(2.)*tof_sigma;
796 HPFLTNB prev_erf = 0., new_erf = 0.;
799 INTNB tof_bin_last = tof_half_nb_bins;
800 INTNB tof_bin_first = -tof_half_nb_bins;
808 INTNB tof_bin_first_for_voxel = 0, tof_bin_last_for_voxel = 0;
813 for(
int i = 0; i < 3; ++i )
815 if( delta_pos[ i ] != 0.0 )
817 alphaFirst[i] = (-
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
818 alphaLast[i] = (
mp_halfFOV[i] - event1[i]) / (delta_pos[ i ]);
819 alphaMin = (std::max)(alphaMin,(std::min)(alphaFirst[i],alphaLast[i]));
820 alphaMax = (std::min)(alphaMax,(std::max)(alphaFirst[i],alphaLast[i]));
826 if( alphaMax <= alphaMin )
return 0;
830 int iMin = 0, iMax = 0;
831 int jMin = 0, jMax = 0;
832 int kMin = 0, kMax = 0;
835 if( delta_pos[ 0 ] > 0.0 )
837 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMin * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
838 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMax * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
840 else if( delta_pos[ 0 ] < 0.0 )
842 iMin = ::ceil( ( mp_nbVox[ 0 ] + 1 ) - (
mp_halfFOV[ 0 ] - alphaMax * delta_pos[ 0 ] - event1[ 0 ] ) /
mp_sizeVox[0] );
843 iMax = ::floor( 1 + ( event1[ 0 ] + alphaMin * delta_pos[ 0 ] - (-
mp_halfFOV[ 0 ]) ) /
mp_sizeVox[0] );
845 if( delta_pos[ 0 ] == 0. )
851 if( delta_pos[ 1 ] > 0. )
853 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMin * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
854 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMax * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
856 else if( delta_pos[ 1 ] < 0. )
858 jMin = ::ceil( ( mp_nbVox[ 1 ] + 1 ) - (
mp_halfFOV[ 1 ] - alphaMax * delta_pos[ 1 ] - event1[ 1 ] ) /
mp_sizeVox[1] );
859 jMax = ::floor( 1 + ( event1[ 1 ] + alphaMin * delta_pos[ 1 ] - (-
mp_halfFOV[ 1 ]) ) /
mp_sizeVox[1] );
861 else if( delta_pos[ 1 ] == 0. )
867 if( delta_pos[ 2 ] > 0. )
869 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMin * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
870 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMax * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
872 else if( delta_pos[ 2 ] < 0. )
874 kMin = ::ceil( ( mp_nbVox[ 2 ] + 1 ) - (
mp_halfFOV[ 2 ] - alphaMax * delta_pos[ 2 ] - event1[ 2 ] ) /
mp_sizeVox[2] );
875 kMax = ::floor( 1 + ( event1[ 2 ] + alphaMin * delta_pos[ 2 ] - (-
mp_halfFOV[ 2 ]) ) /
mp_sizeVox[2] );
877 else if( delta_pos[ 2 ] == 0. )
883 int n = ( iMax - iMin + 1 ) + ( jMax - jMin + 1 )
884 + ( kMax - kMin + 1 );
888 FLTNB *alpha =
new FLTNB[ mp_nbVox[ 0 ] + mp_nbVox[ 1 ] + mp_nbVox[ 2 ] + 3 ];
889 FLTNB *tmpAlpha =
new FLTNB[ mp_nbVox[ 0 ] + mp_nbVox[ 1 ] + mp_nbVox[ 2 ] + 3 ];
890 FLTNB *alphaX =
new FLTNB[ ( mp_nbVox[ 0 ] + 1 ) ];
891 FLTNB *alphaY =
new FLTNB[ ( mp_nbVox[ 1 ] + 1 ) ];
892 FLTNB *alphaZ =
new FLTNB[ ( mp_nbVox[ 2 ] + 1 ) ];
897 for (
INTNB tof_bin=0; tof_bin<tof_nb_bins; tof_bin++) tof_weights_temp[tof_bin] = 0.;
899 INTNB iElement = iMax - iMin + 1;
903 if( delta_pos[ 0 ] > 0. )
905 for(
int i = iMin; i <= iMax; ++i )
908 else if( delta_pos[ 0 ] < 0. )
910 for(
int i = iMax; i >= iMin; --i )
916 INTNB jElement = jMax - jMin + 1;
920 if( delta_pos[ 1 ] > 0. )
922 for(
int j = jMin; j <= jMax; ++j )
925 else if( delta_pos[ 1 ] < 0. )
927 for(
int j = jMax; j >= jMin; --j )
933 INTNB kElement = kMax - kMin + 1;
937 if( delta_pos[ 2 ] > 0. )
939 for(
int k = kMin; k <= kMax; ++k )
942 else if( delta_pos[ 2 ] < 0. )
944 for(
int k = kMax; k >= kMin; --k )
950 alphaX, alphaX + iElement,
954 ::memcpy( tmpAlpha, alpha, ( iElement ) *
sizeof(
FLTNB ) );
957 alphaY, alphaY + jElement,
958 tmpAlpha, tmpAlpha + iElement,
961 ::memcpy( tmpAlpha, alpha, ( iElement + jElement ) *
sizeof(
FLTNB ) );
964 alphaZ, alphaZ + kElement,
965 tmpAlpha, tmpAlpha + iElement + jElement,
977 FLTNB alphaMid = 0.0;
978 INTNB i = 0, j = 0, k = 0;
979 FLTNB *pAlpha = &alpha[ 1 ];
980 FLTNB *pAlphaPrevious = &alpha[ 0 ];
985 for(
int nP = 0; nP < n - 1; ++nP, ++pAlpha, ++pAlphaPrevious )
987 alphaMid = ( *pAlpha + *pAlphaPrevious ) * 0.5;
989 i = alphaMid * i2 + i1;
990 if( i < 1 || i > mp_nbVox[ 0 ] )
continue;
992 j = alphaMid * j2 + j1;
993 if( j < 1 || j > mp_nbVox[ 1 ] )
continue;
995 k = alphaMid * k2 + k1;
996 if( k < 1 || k > mp_nbVox[ 2 ] )
continue;
998 numVox = ( i - 1 ) + ( j - 1 ) * mp_nbVox[0] + ( k - 1 ) * mp_nbVox[0] * mp_nbVox[1];
1003 coeff = length_LOR * ( *pAlpha - *pAlphaPrevious );
1015 tof_bin_first_for_voxel = max(tof_bin_first , (
INTNB)(ceil( (alphaMid * length_LOR - tof_half_span - length_LOR_half ) /
m_TOFBinSizeInMm )));
1016 tof_bin_last_for_voxel = min(tof_bin_last , (
INTNB)(floor( (alphaMid * length_LOR + tof_half_span - length_LOR_half) /
m_TOFBinSizeInMm )));
1019 lor_tof_center = length_LOR_half + tof_bin_first_for_voxel *
m_TOFBinSizeInMm;
1022 tof_bin_first_for_voxel += tof_half_nb_bins;
1023 tof_bin_last_for_voxel += tof_half_nb_bins;
1029 HPFLTNB temp = std::min(tof_half_span,std::max(-tof_half_span, lor_tof_center - m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1030 prev_erf = erf(temp/tof_sigma_sqrt2);
1035 for (
INTNB tof_bin=tof_bin_first_for_voxel; tof_bin<=tof_bin_last_for_voxel; tof_bin++)
1055 HPFLTNB temp = std::min(tof_half_span, std::max(-tof_half_span, lor_tof_center + m_TOFBinSizeInMm/2. - alphaMid * length_LOR));
1056 new_erf = erf(temp/tof_sigma_sqrt2);
1057 tof_weights_temp[tof_bin] = 0.5 * fabs(new_erf - prev_erf);
1067 HPFLTNB temp = (alphaMid * length_LOR - lor_tof_center) / tof_sigma;
1085 ap_ProjectionLine->
AddVoxelAllTOFBins(a_direction, numVox, coeff, tof_weights_temp, tof_bin_first_for_voxel, tof_bin_last_for_voxel);
1094 delete[] tof_weights_temp;
1096 #ifdef CASTOR_VERBOSE 1099 Cout(
"iProjectorClassicSiddon::Project with TOF bins -> Exit function" << endl);
void ShowHelpSpecific()
A function used to show help about the child projector.
bool m_compatibleWithSPECTAttenuationCorrection
int ProjectTOFHistogram(int a_direction, oProjectionLine *ap_ProjectionLine)
FLTNB m_TOFGaussianNormCoef
void AddVoxelAllTOFBins(int a_direction, INTNB a_voxelIndex, FLTNB a_voxelWeight, HPFLTNB *a_tofWeights, INTNB a_tofBinFirst, INTNB a_tofBinLast)
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.
int ReadOptionsList(const string &a_optionsList)
iProjectorClassicSiddon()
The constructor of iProjectorClassicSiddon.
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)
FLTNB m_TOFResolutionInMm
~iProjectorClassicSiddon()
The destructor of iProjectorClassicSiddon.
int CheckSpecificParameters()
A private function used to check the parameters settings specific to the child projector.
int ProjectTOFListmode(int a_direction, oProjectionLine *ap_ProjectionLine)
This class is designed to manage and store system matrix elements associated to a vEvent...
INTNB EstimateMaxNumberOfVoxelsPerLine()
This function is used to compute and provide an estimate of the maximum number of voxels that could c...
int ReadConfigurationFile(const string &a_configurationFile)
FLTNB m_TOFPrecomputedSamplingFactor
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).
INTNB GetNbVoxX()
Get the number of voxels along the X axis.
INTNB GetNbVoxZ()
Get the number of voxels along the Z axis.
int ProjectWithoutTOF(int a_direction, oProjectionLine *ap_ProjectionLine)
bool m_compatibleWithCompression
int InitializeSpecific()
This function is used to initialize specific stuff 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